Release 1.1.37.
[wine/gsoc-2012-control.git] / dlls / cabinet / fdi.c
blobde64f025bd3cb3698dd13227161b7c424284c434
1 /*
2 * File Decompression Interface
4 * Copyright 2000-2002 Stuart Caie
5 * Copyright 2002 Patrik Stridvall
6 * Copyright 2003 Greg Turner
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * This is a largely redundant reimplementation of the stuff in cabextract.c. It
24 * would be theoretically preferable to have only one, shared implementation, however
25 * there are semantic differences which may discourage efforts to unify the two. It
26 * should be possible, if awkward, to go back and reimplement cabextract.c using FDI.
27 * But this approach would be quite a bit less performant. Probably a better way
28 * would be to create a "library" of routines in cabextract.c which do the actual
29 * decompression, and have both fdi.c and cabextract share those routines. The rest
30 * of the code is not sufficiently similar to merit a shared implementation.
32 * The worst thing about this API is the bug. "The bug" is this: when you extract a
33 * cabinet, it /always/ informs you (via the hasnext field of PFDICABINETINFO), that
34 * there is no subsequent cabinet, even if there is one. wine faithfully reproduces
35 * this behavior.
37 * TODO:
39 * Wine does not implement the AFAIK undocumented "enumerate" callback during
40 * FDICopy. It is implemented in Windows and therefore worth investigating...
42 * Lots of pointers flying around here... am I leaking RAM?
44 * WTF is FDITruncate?
46 * Probably, I need to weed out some dead code-paths.
48 * Test unit(s).
50 * The fdintNEXT_CABINET callbacks are probably not working quite as they should.
51 * There are several FIXME's in the source describing some of the deficiencies in
52 * some detail. Additionally, we do not do a very good job of returning the right
53 * error codes to this callback.
55 * FDICopy and fdi_decomp are incomprehensibly large; separating these into smaller
56 * functions would be nice.
58 * -gmt
61 #include "config.h"
63 #include <stdarg.h>
64 #include <stdio.h>
66 #include "windef.h"
67 #include "winbase.h"
68 #include "winerror.h"
69 #include "fdi.h"
70 #include "cabinet.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
76 THOSE_ZIP_CONSTS;
78 struct fdi_file {
79 struct fdi_file *next; /* next file in sequence */
80 LPCSTR filename; /* output name of file */
81 int fh; /* open file handle or NULL */
82 cab_ULONG length; /* uncompressed length of file */
83 cab_ULONG offset; /* uncompressed offset in folder */
84 cab_UWORD index; /* magic index number of folder */
85 cab_UWORD time, date, attribs; /* MS-DOS time/date/attributes */
86 BOOL oppressed; /* never to be processed */
89 struct fdi_folder {
90 struct fdi_folder *next;
91 cab_off_t offset; /* offset to data blocks (32 bit) */
92 cab_UWORD comp_type; /* compression format/window size */
93 cab_ULONG comp_size; /* compressed size of folder */
94 cab_UBYTE num_splits; /* number of split blocks + 1 */
95 cab_UWORD num_blocks; /* total number of blocks */
99 * this structure fills the gaps between what is available in a PFDICABINETINFO
100 * vs what is needed by FDICopy. Memory allocated for these becomes the responsibility
101 * of the caller to free. Yes, I am aware that this is totally, utterly inelegant.
102 * To make things even more unnecessarily confusing, we now attach these to the
103 * fdi_decomp_state.
105 typedef struct {
106 char *prevname, *previnfo;
107 char *nextname, *nextinfo;
108 BOOL hasnext; /* bug free indicator */
109 int folder_resv, header_resv;
110 cab_UBYTE block_resv;
111 } MORE_ISCAB_INFO, *PMORE_ISCAB_INFO;
114 * ugh, well, this ended up being pretty damn silly...
115 * now that I've conceded to build equivalent structures to struct cab.*,
116 * I should have just used those, or, better yet, unified the two... sue me.
117 * (Note to Microsoft: That's a joke. Please /don't/ actually sue me! -gmt).
118 * Nevertheless, I've come this far, it works, so I'm not gonna change it
119 * for now. This implementation has significant semantic differences anyhow.
122 typedef struct fdi_cds_fwd {
123 void *hfdi; /* the hfdi we are using */
124 INT_PTR filehf, cabhf; /* file handle we are using */
125 struct fdi_folder *current; /* current folder we're extracting from */
126 cab_ULONG offset; /* uncompressed offset within folder */
127 cab_UBYTE *outpos; /* (high level) start of data to use up */
128 cab_UWORD outlen; /* (high level) amount of data to use up */
129 int (*decompress)(int, int, struct fdi_cds_fwd *); /* chosen compress fn */
130 cab_UBYTE inbuf[CAB_INPUTMAX+2]; /* +2 for lzx bitbuffer overflows! */
131 cab_UBYTE outbuf[CAB_BLOCKMAX];
132 union {
133 struct ZIPstate zip;
134 struct QTMstate qtm;
135 struct LZXstate lzx;
136 } methods;
137 /* some temp variables for use during decompression */
138 cab_UBYTE q_length_base[27], q_length_extra[27], q_extra_bits[42];
139 cab_ULONG q_position_base[42];
140 cab_ULONG lzx_position_base[51];
141 cab_UBYTE extra_bits[51];
142 USHORT setID; /* Cabinet set ID */
143 USHORT iCabinet; /* Cabinet number in set (0 based) */
144 struct fdi_cds_fwd *decomp_cab;
145 MORE_ISCAB_INFO mii;
146 struct fdi_folder *firstfol;
147 struct fdi_file *firstfile;
148 struct fdi_cds_fwd *next;
149 } fdi_decomp_state;
151 /****************************************************************
152 * QTMupdatemodel (internal)
154 static void QTMupdatemodel(struct QTMmodel *model, int sym) {
155 struct QTMmodelsym temp;
156 int i, j;
158 for (i = 0; i < sym; i++) model->syms[i].cumfreq += 8;
160 if (model->syms[0].cumfreq > 3800) {
161 if (--model->shiftsleft) {
162 for (i = model->entries - 1; i >= 0; i--) {
163 /* -1, not -2; the 0 entry saves this */
164 model->syms[i].cumfreq >>= 1;
165 if (model->syms[i].cumfreq <= model->syms[i+1].cumfreq) {
166 model->syms[i].cumfreq = model->syms[i+1].cumfreq + 1;
170 else {
171 model->shiftsleft = 50;
172 for (i = 0; i < model->entries ; i++) {
173 /* no -1, want to include the 0 entry */
174 /* this converts cumfreqs into frequencies, then shifts right */
175 model->syms[i].cumfreq -= model->syms[i+1].cumfreq;
176 model->syms[i].cumfreq++; /* avoid losing things entirely */
177 model->syms[i].cumfreq >>= 1;
180 /* now sort by frequencies, decreasing order -- this must be an
181 * inplace selection sort, or a sort with the same (in)stability
182 * characteristics
184 for (i = 0; i < model->entries - 1; i++) {
185 for (j = i + 1; j < model->entries; j++) {
186 if (model->syms[i].cumfreq < model->syms[j].cumfreq) {
187 temp = model->syms[i];
188 model->syms[i] = model->syms[j];
189 model->syms[j] = temp;
194 /* then convert frequencies back to cumfreq */
195 for (i = model->entries - 1; i >= 0; i--) {
196 model->syms[i].cumfreq += model->syms[i+1].cumfreq;
198 /* then update the other part of the table */
199 for (i = 0; i < model->entries; i++) {
200 model->tabloc[model->syms[i].sym] = i;
206 /*************************************************************************
207 * make_decode_table (internal)
209 * This function was coded by David Tritscher. It builds a fast huffman
210 * decoding table out of just a canonical huffman code lengths table.
212 * PARAMS
213 * nsyms: total number of symbols in this huffman tree.
214 * nbits: any symbols with a code length of nbits or less can be decoded
215 * in one lookup of the table.
216 * length: A table to get code lengths from [0 to syms-1]
217 * table: The table to fill up with decoded symbols and pointers.
219 * RETURNS
220 * OK: 0
221 * error: 1
223 static int make_decode_table(cab_ULONG nsyms, cab_ULONG nbits,
224 const cab_UBYTE *length, cab_UWORD *table) {
225 register cab_UWORD sym;
226 register cab_ULONG leaf;
227 register cab_UBYTE bit_num = 1;
228 cab_ULONG fill;
229 cab_ULONG pos = 0; /* the current position in the decode table */
230 cab_ULONG table_mask = 1 << nbits;
231 cab_ULONG bit_mask = table_mask >> 1; /* don't do 0 length codes */
232 cab_ULONG next_symbol = bit_mask; /* base of allocation for long codes */
234 /* fill entries for codes short enough for a direct mapping */
235 while (bit_num <= nbits) {
236 for (sym = 0; sym < nsyms; sym++) {
237 if (length[sym] == bit_num) {
238 leaf = pos;
240 if((pos += bit_mask) > table_mask) return 1; /* table overrun */
242 /* fill all possible lookups of this symbol with the symbol itself */
243 fill = bit_mask;
244 while (fill-- > 0) table[leaf++] = sym;
247 bit_mask >>= 1;
248 bit_num++;
251 /* if there are any codes longer than nbits */
252 if (pos != table_mask) {
253 /* clear the remainder of the table */
254 for (sym = pos; sym < table_mask; sym++) table[sym] = 0;
256 /* give ourselves room for codes to grow by up to 16 more bits */
257 pos <<= 16;
258 table_mask <<= 16;
259 bit_mask = 1 << 15;
261 while (bit_num <= 16) {
262 for (sym = 0; sym < nsyms; sym++) {
263 if (length[sym] == bit_num) {
264 leaf = pos >> 16;
265 for (fill = 0; fill < bit_num - nbits; fill++) {
266 /* if this path hasn't been taken yet, 'allocate' two entries */
267 if (table[leaf] == 0) {
268 table[(next_symbol << 1)] = 0;
269 table[(next_symbol << 1) + 1] = 0;
270 table[leaf] = next_symbol++;
272 /* follow the path and select either left or right for next bit */
273 leaf = table[leaf] << 1;
274 if ((pos >> (15-fill)) & 1) leaf++;
276 table[leaf] = sym;
278 if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
281 bit_mask >>= 1;
282 bit_num++;
286 /* full table? */
287 if (pos == table_mask) return 0;
289 /* either erroneous table, or all elements are 0 - let's find out. */
290 for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1;
291 return 0;
294 /*************************************************************************
295 * checksum (internal)
297 static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum) {
298 int len;
299 cab_ULONG ul = 0;
301 for (len = bytes >> 2; len--; data += 4) {
302 csum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
305 switch (bytes & 3) {
306 case 3: ul |= *data++ << 16;
307 case 2: ul |= *data++ << 8;
308 case 1: ul |= *data;
310 csum ^= ul;
312 return csum;
315 /***********************************************************************
316 * FDICreate (CABINET.20)
318 * Provided with several callbacks (all of them are mandatory),
319 * returns a handle which can be used to perform operations
320 * on cabinet files.
322 * PARAMS
323 * pfnalloc [I] A pointer to a function which allocates ram. Uses
324 * the same interface as malloc.
325 * pfnfree [I] A pointer to a function which frees ram. Uses the
326 * same interface as free.
327 * pfnopen [I] A pointer to a function which opens a file. Uses
328 * the same interface as _open.
329 * pfnread [I] A pointer to a function which reads from a file into
330 * a caller-provided buffer. Uses the same interface
331 * as _read
332 * pfnwrite [I] A pointer to a function which writes to a file from
333 * a caller-provided buffer. Uses the same interface
334 * as _write.
335 * pfnclose [I] A pointer to a function which closes a file handle.
336 * Uses the same interface as _close.
337 * pfnseek [I] A pointer to a function which seeks in a file.
338 * Uses the same interface as _lseek.
339 * cpuType [I] The type of CPU; ignored in wine (recommended value:
340 * cpuUNKNOWN, aka -1).
341 * perf [IO] A pointer to an ERF structure. When FDICreate
342 * returns an error condition, error information may
343 * be found here as well as from GetLastError.
345 * RETURNS
346 * On success, returns an FDI handle of type HFDI.
347 * On failure, the NULL file handle is returned. Error
348 * info can be retrieved from perf.
350 * INCLUDES
351 * fdi.h
354 HFDI __cdecl FDICreate(
355 PFNALLOC pfnalloc,
356 PFNFREE pfnfree,
357 PFNOPEN pfnopen,
358 PFNREAD pfnread,
359 PFNWRITE pfnwrite,
360 PFNCLOSE pfnclose,
361 PFNSEEK pfnseek,
362 int cpuType,
363 PERF perf)
365 HFDI rv;
367 TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, "
368 "pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
369 pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
370 cpuType, perf);
372 if ((!pfnalloc) || (!pfnfree)) {
373 perf->erfOper = FDIERROR_NONE;
374 perf->erfType = ERROR_BAD_ARGUMENTS;
375 perf->fError = TRUE;
377 SetLastError(ERROR_BAD_ARGUMENTS);
378 return NULL;
381 if (!((rv = (*pfnalloc)(sizeof(FDI_Int))))) {
382 perf->erfOper = FDIERROR_ALLOC_FAIL;
383 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
384 perf->fError = TRUE;
386 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
387 return NULL;
390 PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
391 PFDI_INT(rv)->pfnalloc = pfnalloc;
392 PFDI_INT(rv)->pfnfree = pfnfree;
393 PFDI_INT(rv)->pfnopen = pfnopen;
394 PFDI_INT(rv)->pfnread = pfnread;
395 PFDI_INT(rv)->pfnwrite = pfnwrite;
396 PFDI_INT(rv)->pfnclose = pfnclose;
397 PFDI_INT(rv)->pfnseek = pfnseek;
398 /* no-brainer: we ignore the cpu type; this is only used
399 for the 16-bit versions in Windows anyhow... */
400 PFDI_INT(rv)->perf = perf;
402 return rv;
405 /*******************************************************************
406 * FDI_getoffset (internal)
408 * returns the file pointer position of a file handle.
410 static long FDI_getoffset(HFDI hfdi, INT_PTR hf)
412 return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
415 /**********************************************************************
416 * FDI_read_string (internal)
418 * allocate and read an arbitrarily long string from the cabinet
420 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
422 size_t len=256,
423 base = FDI_getoffset(hfdi, hf),
424 maxlen = cabsize - base;
425 BOOL ok = FALSE;
426 unsigned int i;
427 cab_UBYTE *buf = NULL;
429 TRACE("(hfdi == ^%p, hf == %ld, cabsize == %ld)\n", hfdi, hf, cabsize);
431 do {
432 if (len > maxlen) len = maxlen;
433 if (!(buf = PFDI_ALLOC(hfdi, len))) break;
434 if (!PFDI_READ(hfdi, hf, buf, len)) break;
436 /* search for a null terminator in what we've just read */
437 for (i=0; i < len; i++) {
438 if (!buf[i]) {ok=TRUE; break;}
441 if (!ok) {
442 if (len == maxlen) {
443 ERR("cabinet is truncated\n");
444 break;
446 /* The buffer is too small for the string. Reset the file to the point
447 * were we started, free the buffer and increase the size for the next try
449 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
450 PFDI_FREE(hfdi, buf);
451 buf = NULL;
452 len *= 2;
454 } while (!ok);
456 if (!ok) {
457 if (buf)
458 PFDI_FREE(hfdi, buf);
459 else
460 ERR("out of memory!\n");
461 return NULL;
464 /* otherwise, set the stream to just after the string and return */
465 PFDI_SEEK(hfdi, hf, base + strlen((char *)buf) + 1, SEEK_SET);
467 return (char *) buf;
470 /******************************************************************
471 * FDI_read_entries (internal)
473 * process the cabinet header in the style of FDIIsCabinet, but
474 * without the sanity checks (and bug)
476 static BOOL FDI_read_entries(
477 HFDI hfdi,
478 INT_PTR hf,
479 PFDICABINETINFO pfdici,
480 PMORE_ISCAB_INFO pmii)
482 int num_folders, num_files, header_resv, folder_resv = 0;
483 LONG base_offset, cabsize;
484 USHORT setid, cabidx, flags;
485 cab_UBYTE buf[64], block_resv;
486 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
488 TRACE("(hfdi == ^%p, hf == %ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
491 * FIXME: I just noticed that I am memorizing the initial file pointer
492 * offset and restoring it before reading in the rest of the header
493 * information in the cabinet. Perhaps that's correct -- that is, perhaps
494 * this API is supposed to support "streaming" cabinets which are embedded
495 * in other files, or cabinets which begin at file offsets other than zero.
496 * Otherwise, I should instead go to the absolute beginning of the file.
497 * (Either way, the semantics of wine's FDICopy require me to leave the
498 * file pointer where it is afterwards -- If Windows does not do so, we
499 * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
501 * So, the answer lies in Windows; will native cabinet.dll recognize a
502 * cabinet "file" embedded in another file? Note that cabextract.c does
503 * support this, which implies that Microsoft's might. I haven't tried it
504 * yet so I don't know. ATM, most of wine's FDI cabinet routines (except
505 * this one) would not work in this way. To fix it, we could just make the
506 * various references to absolute file positions in the code relative to an
507 * initial "beginning" offset. Because the FDICopy API doesn't take a
508 * file-handle like this one, we would therein need to search through the
509 * file for the beginning of the cabinet (as we also do in cabextract.c).
510 * Note that this limits us to a maximum of one cabinet per. file: the first.
512 * So, in summary: either the code below is wrong, or the rest of fdi.c is
513 * wrong... I cannot imagine that both are correct ;) One of these flaws
514 * should be fixed after determining the behavior on Windows. We ought
515 * to check both FDIIsCabinet and FDICopy for the right behavior.
517 * -gmt
520 /* get basic offset & size info */
521 base_offset = FDI_getoffset(hfdi, hf);
523 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
524 if (pmii) {
525 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
526 PFDI_INT(hfdi)->perf->erfType = 0;
527 PFDI_INT(hfdi)->perf->fError = TRUE;
529 return FALSE;
532 cabsize = FDI_getoffset(hfdi, hf);
534 if ((cabsize == -1) || (base_offset == -1) ||
535 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
536 if (pmii) {
537 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
538 PFDI_INT(hfdi)->perf->erfType = 0;
539 PFDI_INT(hfdi)->perf->fError = TRUE;
541 return FALSE;
544 /* read in the CFHEADER */
545 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
546 if (pmii) {
547 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
548 PFDI_INT(hfdi)->perf->erfType = 0;
549 PFDI_INT(hfdi)->perf->fError = TRUE;
551 return FALSE;
554 /* check basic MSCF signature */
555 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
556 if (pmii) {
557 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
558 PFDI_INT(hfdi)->perf->erfType = 0;
559 PFDI_INT(hfdi)->perf->fError = TRUE;
561 return FALSE;
564 /* get the number of folders */
565 num_folders = EndGetI16(buf+cfhead_NumFolders);
566 if (num_folders == 0) {
567 /* PONDERME: is this really invalid? */
568 WARN("weird cabinet detect failure: no folders in cabinet\n");
569 if (pmii) {
570 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
571 PFDI_INT(hfdi)->perf->erfType = 0;
572 PFDI_INT(hfdi)->perf->fError = TRUE;
574 return FALSE;
577 /* get the number of files */
578 num_files = EndGetI16(buf+cfhead_NumFiles);
579 if (num_files == 0) {
580 /* PONDERME: is this really invalid? */
581 WARN("weird cabinet detect failure: no files in cabinet\n");
582 if (pmii) {
583 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
584 PFDI_INT(hfdi)->perf->erfType = 0;
585 PFDI_INT(hfdi)->perf->fError = TRUE;
587 return FALSE;
590 /* setid */
591 setid = EndGetI16(buf+cfhead_SetID);
593 /* cabinet (set) index */
594 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
596 /* check the header revision */
597 if ((buf[cfhead_MajorVersion] > 1) ||
598 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
600 WARN("cabinet format version > 1.3\n");
601 if (pmii) {
602 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
603 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
604 PFDI_INT(hfdi)->perf->fError = TRUE;
606 return FALSE;
609 /* pull the flags out */
610 flags = EndGetI16(buf+cfhead_Flags);
612 /* read the reserved-sizes part of header, if present */
613 if (flags & cfheadRESERVE_PRESENT) {
614 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
615 ERR("bunk reserve-sizes?\n");
616 if (pmii) {
617 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
618 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
619 PFDI_INT(hfdi)->perf->fError = TRUE;
621 return FALSE;
624 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
625 if (pmii) pmii->header_resv = header_resv;
626 folder_resv = buf[cfheadext_FolderReserved];
627 if (pmii) pmii->folder_resv = folder_resv;
628 block_resv = buf[cfheadext_DataReserved];
629 if (pmii) pmii->block_resv = block_resv;
631 if (header_resv > 60000) {
632 WARN("WARNING; header reserved space > 60000\n");
635 /* skip the reserved header */
636 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
637 ERR("seek failure: header_resv\n");
638 if (pmii) {
639 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
640 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
641 PFDI_INT(hfdi)->perf->fError = TRUE;
643 return FALSE;
647 if (flags & cfheadPREV_CABINET) {
648 prevname = FDI_read_string(hfdi, hf, cabsize);
649 if (!prevname) {
650 if (pmii) {
651 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
652 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
653 PFDI_INT(hfdi)->perf->fError = TRUE;
655 return FALSE;
656 } else
657 if (pmii)
658 pmii->prevname = prevname;
659 else
660 PFDI_FREE(hfdi, prevname);
661 previnfo = FDI_read_string(hfdi, hf, cabsize);
662 if (previnfo) {
663 if (pmii)
664 pmii->previnfo = previnfo;
665 else
666 PFDI_FREE(hfdi, previnfo);
670 if (flags & cfheadNEXT_CABINET) {
671 if (pmii)
672 pmii->hasnext = TRUE;
673 nextname = FDI_read_string(hfdi, hf, cabsize);
674 if (!nextname) {
675 if ((flags & cfheadPREV_CABINET) && pmii) {
676 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
677 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
679 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
680 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
681 PFDI_INT(hfdi)->perf->fError = TRUE;
682 return FALSE;
683 } else
684 if (pmii)
685 pmii->nextname = nextname;
686 else
687 PFDI_FREE(hfdi, nextname);
688 nextinfo = FDI_read_string(hfdi, hf, cabsize);
689 if (nextinfo) {
690 if (pmii)
691 pmii->nextinfo = nextinfo;
692 else
693 PFDI_FREE(hfdi, nextinfo);
697 /* we could process the whole cabinet searching for problems;
698 instead lets stop here. Now let's fill out the paperwork */
699 pfdici->cbCabinet = cabsize;
700 pfdici->cFolders = num_folders;
701 pfdici->cFiles = num_files;
702 pfdici->setID = setid;
703 pfdici->iCabinet = cabidx;
704 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
705 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
706 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
707 return TRUE;
710 /***********************************************************************
711 * FDIIsCabinet (CABINET.21)
713 * Informs the caller as to whether or not the provided file handle is
714 * really a cabinet or not, filling out the provided PFDICABINETINFO
715 * structure with information about the cabinet. Brief explanations of
716 * the elements of this structure are available as comments accompanying
717 * its definition in wine's include/fdi.h.
719 * PARAMS
720 * hfdi [I] An HFDI from FDICreate
721 * hf [I] The file handle about which the caller inquires
722 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
723 * be filled out with information about the cabinet
724 * file indicated by hf if, indeed, it is determined
725 * to be a cabinet.
727 * RETURNS
728 * TRUE if the file is a cabinet. The info pointed to by pfdici will
729 * be provided.
730 * FALSE if the file is not a cabinet, or if an error was encountered
731 * while processing the cabinet. The PERF structure provided to
732 * FDICreate can be queried for more error information.
734 * INCLUDES
735 * fdi.c
737 BOOL __cdecl FDIIsCabinet(
738 HFDI hfdi,
739 INT_PTR hf,
740 PFDICABINETINFO pfdici)
742 BOOL rv;
744 TRACE("(hfdi == ^%p, hf == ^%ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
746 if (!REALLY_IS_FDI(hfdi)) {
747 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
748 SetLastError(ERROR_INVALID_HANDLE);
749 return FALSE;
752 if (!hf) {
753 ERR("(!hf)!\n");
754 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
755 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
756 PFDI_INT(hfdi)->perf->fError = TRUE; */
757 SetLastError(ERROR_INVALID_HANDLE);
758 return FALSE;
761 if (!pfdici) {
762 ERR("(!pfdici)!\n");
763 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
764 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
765 PFDI_INT(hfdi)->perf->fError = TRUE; */
766 SetLastError(ERROR_BAD_ARGUMENTS);
767 return FALSE;
769 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
771 if (rv)
772 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
774 return rv;
777 /******************************************************************
778 * QTMfdi_initmodel (internal)
780 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
782 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
783 int i;
784 m->shiftsleft = 4;
785 m->entries = n;
786 m->syms = sym;
787 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
788 for (i = 0; i < n; i++) {
789 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
790 m->syms[i].sym = i+s; /* actual symbol */
791 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
793 m->syms[n].cumfreq = 0;
796 /******************************************************************
797 * QTMfdi_init (internal)
799 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
800 unsigned int wndsize = 1 << window;
801 int msz = window * 2, i;
802 cab_ULONG j;
804 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
805 /* if a previously allocated window is big enough, keep it */
806 if (window < 10 || window > 21) return DECR_DATAFORMAT;
807 if (QTM(actual_size) < wndsize) {
808 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
809 QTM(window) = NULL;
811 if (!QTM(window)) {
812 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
813 QTM(actual_size) = wndsize;
815 QTM(window_size) = wndsize;
816 QTM(window_posn) = 0;
818 /* initialize static slot/extrabits tables */
819 for (i = 0, j = 0; i < 27; i++) {
820 CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
821 CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
823 for (i = 0, j = 0; i < 42; i++) {
824 CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
825 CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
828 /* initialize arithmetic coding models */
830 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
832 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
833 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
834 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
835 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
837 /* model 4 depends on table size, ranges from 20 to 24 */
838 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
839 /* model 5 depends on table size, ranges from 20 to 36 */
840 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
841 /* model 6pos depends on table size, ranges from 20 to 42 */
842 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
843 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
845 return DECR_OK;
848 /************************************************************
849 * LZXfdi_init (internal)
851 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
852 static const cab_UBYTE bits[] =
853 { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
854 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
855 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
856 17, 17, 17};
857 static const cab_ULONG base[] =
858 { 0, 1, 2, 3, 4, 6, 8, 12,
859 16, 24, 32, 48, 64, 96, 128, 192,
860 256, 384, 512, 768, 1024, 1536, 2048, 3072,
861 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
862 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
863 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
864 1835008, 1966080, 2097152};
865 cab_ULONG wndsize = 1 << window;
866 int posn_slots;
868 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
869 /* if a previously allocated window is big enough, keep it */
870 if (window < 15 || window > 21) return DECR_DATAFORMAT;
871 if (LZX(actual_size) < wndsize) {
872 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
873 LZX(window) = NULL;
875 if (!LZX(window)) {
876 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
877 LZX(actual_size) = wndsize;
879 LZX(window_size) = wndsize;
881 /* initialize static tables */
882 memcpy(CAB(extra_bits), bits, sizeof(bits));
883 memcpy(CAB(lzx_position_base), base, sizeof(base));
885 /* calculate required position slots */
886 if (window == 20) posn_slots = 42;
887 else if (window == 21) posn_slots = 50;
888 else posn_slots = window << 1;
890 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
892 LZX(R0) = LZX(R1) = LZX(R2) = 1;
893 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
894 LZX(header_read) = 0;
895 LZX(frames_read) = 0;
896 LZX(block_remaining) = 0;
897 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
898 LZX(intel_curpos) = 0;
899 LZX(intel_started) = 0;
900 LZX(window_posn) = 0;
902 /* initialize tables to 0 (because deltas will be applied to them) */
903 memset(LZX(MAINTREE_len), 0, sizeof(LZX(MAINTREE_len)));
904 memset(LZX(LENGTH_len), 0, sizeof(LZX(LENGTH_len)));
906 return DECR_OK;
909 /****************************************************
910 * NONEfdi_decomp(internal)
912 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
914 if (inlen != outlen) return DECR_ILLEGALDATA;
915 if (outlen > CAB_BLOCKMAX) return DECR_DATAFORMAT;
916 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
917 return DECR_OK;
920 /********************************************************
921 * Ziphuft_free (internal)
923 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
925 register struct Ziphuft *p, *q;
927 /* Go through linked list, freeing from the allocated (t[-1]) address. */
928 p = t;
929 while (p != NULL)
931 q = (--p)->v.t;
932 PFDI_FREE(hfdi, p);
933 p = q;
937 /*********************************************************
938 * fdi_Ziphuft_build (internal)
940 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, const cab_UWORD *d, const cab_UWORD *e,
941 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
943 cab_ULONG a; /* counter for codes of length k */
944 cab_ULONG el; /* length of EOB code (value 256) */
945 cab_ULONG f; /* i repeats in table every f entries */
946 cab_LONG g; /* maximum code length */
947 cab_LONG h; /* table level */
948 register cab_ULONG i; /* counter, current code */
949 register cab_ULONG j; /* counter */
950 register cab_LONG k; /* number of bits in current code */
951 cab_LONG *l; /* stack of bits per table */
952 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
953 register struct Ziphuft *q; /* points to current table */
954 struct Ziphuft r; /* table entry for structure assignment */
955 register cab_LONG w; /* bits before this table == (l * h) */
956 cab_ULONG *xp; /* pointer into x */
957 cab_LONG y; /* number of dummy codes added */
958 cab_ULONG z; /* number of entries in current table */
960 l = ZIP(lx)+1;
962 /* Generate counts for each bit length */
963 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
965 for(i = 0; i < ZIPBMAX+1; ++i)
966 ZIP(c)[i] = 0;
967 p = b; i = n;
970 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
971 } while (--i);
972 if (ZIP(c)[0] == n) /* null input--all zero length codes */
974 *t = NULL;
975 *m = 0;
976 return 0;
979 /* Find minimum and maximum length, bound *m by those */
980 for (j = 1; j <= ZIPBMAX; j++)
981 if (ZIP(c)[j])
982 break;
983 k = j; /* minimum code length */
984 if ((cab_ULONG)*m < j)
985 *m = j;
986 for (i = ZIPBMAX; i; i--)
987 if (ZIP(c)[i])
988 break;
989 g = i; /* maximum code length */
990 if ((cab_ULONG)*m > i)
991 *m = i;
993 /* Adjust last length count to fill out codes, if needed */
994 for (y = 1 << j; j < i; j++, y <<= 1)
995 if ((y -= ZIP(c)[j]) < 0)
996 return 2; /* bad input: more codes than bits */
997 if ((y -= ZIP(c)[i]) < 0)
998 return 2;
999 ZIP(c)[i] += y;
1001 /* Generate starting offsets LONGo the value table for each length */
1002 ZIP(x)[1] = j = 0;
1003 p = ZIP(c) + 1; xp = ZIP(x) + 2;
1004 while (--i)
1005 { /* note that i == g from above */
1006 *xp++ = (j += *p++);
1009 /* Make a table of values in order of bit lengths */
1010 p = b; i = 0;
1012 if ((j = *p++) != 0)
1013 ZIP(v)[ZIP(x)[j]++] = i;
1014 } while (++i < n);
1017 /* Generate the Huffman codes and for each, make the table entries */
1018 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
1019 p = ZIP(v); /* grab values in bit order */
1020 h = -1; /* no tables yet--level -1 */
1021 w = l[-1] = 0; /* no bits decoded yet */
1022 ZIP(u)[0] = NULL; /* just to keep compilers happy */
1023 q = NULL; /* ditto */
1024 z = 0; /* ditto */
1026 /* go through the bit lengths (k already is bits in shortest code) */
1027 for (; k <= g; k++)
1029 a = ZIP(c)[k];
1030 while (a--)
1032 /* here i is the Huffman code of length k bits for value *p */
1033 /* make tables up to required level */
1034 while (k > w + l[h])
1036 w += l[h++]; /* add bits already decoded */
1038 /* compute minimum size table less than or equal to *m bits */
1039 if ((z = g - w) > (cab_ULONG)*m) /* upper limit */
1040 z = *m;
1041 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
1042 { /* too few codes for k-w bit table */
1043 f -= a + 1; /* deduct codes from patterns left */
1044 xp = ZIP(c) + k;
1045 while (++j < z) /* try smaller tables up to z bits */
1047 if ((f <<= 1) <= *++xp)
1048 break; /* enough codes to use up j bits */
1049 f -= *xp; /* else deduct codes from patterns */
1052 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
1053 j = el - w; /* make EOB code end at table */
1054 z = 1 << j; /* table entries for j-bit table */
1055 l[h] = j; /* set table size in stack */
1057 /* allocate and link in new table */
1058 if (!(q = PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
1060 if(h)
1061 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
1062 return 3; /* not enough memory */
1064 *t = q + 1; /* link to list for Ziphuft_free() */
1065 *(t = &(q->v.t)) = NULL;
1066 ZIP(u)[h] = ++q; /* table starts after link */
1068 /* connect to last table, if there is one */
1069 if (h)
1071 ZIP(x)[h] = i; /* save pattern for backing up */
1072 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
1073 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
1074 r.v.t = q; /* pointer to this table */
1075 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
1076 ZIP(u)[h-1][j] = r; /* connect to last table */
1080 /* set up table entry in r */
1081 r.b = (cab_UBYTE)(k - w);
1082 if (p >= ZIP(v) + n)
1083 r.e = 99; /* out of values--invalid code */
1084 else if (*p < s)
1086 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
1087 r.v.n = *p++; /* simple code is just the value */
1089 else
1091 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
1092 r.v.n = d[*p++ - s];
1095 /* fill code-like entries with r */
1096 f = 1 << (k - w);
1097 for (j = i >> w; j < z; j += f)
1098 q[j] = r;
1100 /* backwards increment the k-bit code i */
1101 for (j = 1 << (k - 1); i & j; j >>= 1)
1102 i ^= j;
1103 i ^= j;
1105 /* backup over finished tables */
1106 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
1107 w -= l[--h]; /* don't need to update q */
1111 /* return actual size of base table */
1112 *m = l[0];
1114 /* Return true (1) if we were given an incomplete table */
1115 return y != 0 && g != 1;
1118 /*********************************************************
1119 * fdi_Zipinflate_codes (internal)
1121 static cab_LONG fdi_Zipinflate_codes(const struct Ziphuft *tl, const struct Ziphuft *td,
1122 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
1124 register cab_ULONG e; /* table entry flag/number of extra bits */
1125 cab_ULONG n, d; /* length and index for copy */
1126 cab_ULONG w; /* current window position */
1127 const struct Ziphuft *t; /* pointer to table entry */
1128 cab_ULONG ml, md; /* masks for bl and bd bits */
1129 register cab_ULONG b; /* bit buffer */
1130 register cab_ULONG k; /* number of bits in bit buffer */
1132 /* make local copies of globals */
1133 b = ZIP(bb); /* initialize bit buffer */
1134 k = ZIP(bk);
1135 w = ZIP(window_posn); /* initialize window position */
1137 /* inflate the coded data */
1138 ml = Zipmask[bl]; /* precompute masks for speed */
1139 md = Zipmask[bd];
1141 for(;;)
1143 ZIPNEEDBITS((cab_ULONG)bl)
1144 if((e = (t = tl + (b & ml))->e) > 16)
1147 if (e == 99)
1148 return 1;
1149 ZIPDUMPBITS(t->b)
1150 e -= 16;
1151 ZIPNEEDBITS(e)
1152 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1153 ZIPDUMPBITS(t->b)
1154 if (e == 16) /* then it's a literal */
1155 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
1156 else /* it's an EOB or a length */
1158 /* exit if end of block */
1159 if(e == 15)
1160 break;
1162 /* get length of block to copy */
1163 ZIPNEEDBITS(e)
1164 n = t->v.n + (b & Zipmask[e]);
1165 ZIPDUMPBITS(e);
1167 /* decode distance of block to copy */
1168 ZIPNEEDBITS((cab_ULONG)bd)
1169 if ((e = (t = td + (b & md))->e) > 16)
1170 do {
1171 if (e == 99)
1172 return 1;
1173 ZIPDUMPBITS(t->b)
1174 e -= 16;
1175 ZIPNEEDBITS(e)
1176 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1177 ZIPDUMPBITS(t->b)
1178 ZIPNEEDBITS(e)
1179 d = w - t->v.n - (b & Zipmask[e]);
1180 ZIPDUMPBITS(e)
1183 d &= ZIPWSIZE - 1;
1184 e = ZIPWSIZE - max(d, w);
1185 e = min(e, n);
1186 n -= e;
1189 CAB(outbuf)[w++] = CAB(outbuf)[d++];
1190 } while (--e);
1191 } while (n);
1195 /* restore the globals from the locals */
1196 ZIP(window_posn) = w; /* restore global window pointer */
1197 ZIP(bb) = b; /* restore global bit buffer */
1198 ZIP(bk) = k;
1200 /* done */
1201 return 0;
1204 /***********************************************************
1205 * Zipinflate_stored (internal)
1207 static cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1208 /* "decompress" an inflated type 0 (stored) block. */
1210 cab_ULONG n; /* number of bytes in block */
1211 cab_ULONG w; /* current window position */
1212 register cab_ULONG b; /* bit buffer */
1213 register cab_ULONG k; /* number of bits in bit buffer */
1215 /* make local copies of globals */
1216 b = ZIP(bb); /* initialize bit buffer */
1217 k = ZIP(bk);
1218 w = ZIP(window_posn); /* initialize window position */
1220 /* go to byte boundary */
1221 n = k & 7;
1222 ZIPDUMPBITS(n);
1224 /* get the length and its complement */
1225 ZIPNEEDBITS(16)
1226 n = (b & 0xffff);
1227 ZIPDUMPBITS(16)
1228 ZIPNEEDBITS(16)
1229 if (n != ((~b) & 0xffff))
1230 return 1; /* error in compressed data */
1231 ZIPDUMPBITS(16)
1233 /* read and output the compressed data */
1234 while(n--)
1236 ZIPNEEDBITS(8)
1237 CAB(outbuf)[w++] = (cab_UBYTE)b;
1238 ZIPDUMPBITS(8)
1241 /* restore the globals from the locals */
1242 ZIP(window_posn) = w; /* restore global window pointer */
1243 ZIP(bb) = b; /* restore global bit buffer */
1244 ZIP(bk) = k;
1245 return 0;
1248 /******************************************************
1249 * fdi_Zipinflate_fixed (internal)
1251 static cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1253 struct Ziphuft *fixed_tl;
1254 struct Ziphuft *fixed_td;
1255 cab_LONG fixed_bl, fixed_bd;
1256 cab_LONG i; /* temporary variable */
1257 cab_ULONG *l;
1259 l = ZIP(ll);
1261 /* literal table */
1262 for(i = 0; i < 144; i++)
1263 l[i] = 8;
1264 for(; i < 256; i++)
1265 l[i] = 9;
1266 for(; i < 280; i++)
1267 l[i] = 7;
1268 for(; i < 288; i++) /* make a complete, but wrong code set */
1269 l[i] = 8;
1270 fixed_bl = 7;
1271 if((i = fdi_Ziphuft_build(l, 288, 257, Zipcplens, Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1272 return i;
1274 /* distance table */
1275 for(i = 0; i < 30; i++) /* make an incomplete code set */
1276 l[i] = 5;
1277 fixed_bd = 5;
1278 if((i = fdi_Ziphuft_build(l, 30, 0, Zipcpdist, Zipcpdext, &fixed_td, &fixed_bd, decomp_state)) > 1)
1280 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1281 return i;
1284 /* decompress until an end-of-block code */
1285 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1287 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1288 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1289 return i;
1292 /**************************************************************
1293 * fdi_Zipinflate_dynamic (internal)
1295 static cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1296 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1298 cab_LONG i; /* temporary variables */
1299 cab_ULONG j;
1300 cab_ULONG *ll;
1301 cab_ULONG l; /* last length */
1302 cab_ULONG m; /* mask for bit lengths table */
1303 cab_ULONG n; /* number of lengths to get */
1304 struct Ziphuft *tl; /* literal/length code table */
1305 struct Ziphuft *td; /* distance code table */
1306 cab_LONG bl; /* lookup bits for tl */
1307 cab_LONG bd; /* lookup bits for td */
1308 cab_ULONG nb; /* number of bit length codes */
1309 cab_ULONG nl; /* number of literal/length codes */
1310 cab_ULONG nd; /* number of distance codes */
1311 register cab_ULONG b; /* bit buffer */
1312 register cab_ULONG k; /* number of bits in bit buffer */
1314 /* make local bit buffer */
1315 b = ZIP(bb);
1316 k = ZIP(bk);
1317 ll = ZIP(ll);
1319 /* read in table lengths */
1320 ZIPNEEDBITS(5)
1321 nl = 257 + (b & 0x1f); /* number of literal/length codes */
1322 ZIPDUMPBITS(5)
1323 ZIPNEEDBITS(5)
1324 nd = 1 + (b & 0x1f); /* number of distance codes */
1325 ZIPDUMPBITS(5)
1326 ZIPNEEDBITS(4)
1327 nb = 4 + (b & 0xf); /* number of bit length codes */
1328 ZIPDUMPBITS(4)
1329 if(nl > 288 || nd > 32)
1330 return 1; /* bad lengths */
1332 /* read in bit-length-code lengths */
1333 for(j = 0; j < nb; j++)
1335 ZIPNEEDBITS(3)
1336 ll[Zipborder[j]] = b & 7;
1337 ZIPDUMPBITS(3)
1339 for(; j < 19; j++)
1340 ll[Zipborder[j]] = 0;
1342 /* build decoding table for trees--single level, 7 bit lookup */
1343 bl = 7;
1344 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1346 if(i == 1)
1347 fdi_Ziphuft_free(CAB(hfdi), tl);
1348 return i; /* incomplete code set */
1351 /* read in literal and distance code lengths */
1352 n = nl + nd;
1353 m = Zipmask[bl];
1354 i = l = 0;
1355 while((cab_ULONG)i < n)
1357 ZIPNEEDBITS((cab_ULONG)bl)
1358 j = (td = tl + (b & m))->b;
1359 ZIPDUMPBITS(j)
1360 j = td->v.n;
1361 if (j < 16) /* length of code in bits (0..15) */
1362 ll[i++] = l = j; /* save last length in l */
1363 else if (j == 16) /* repeat last length 3 to 6 times */
1365 ZIPNEEDBITS(2)
1366 j = 3 + (b & 3);
1367 ZIPDUMPBITS(2)
1368 if((cab_ULONG)i + j > n)
1369 return 1;
1370 while (j--)
1371 ll[i++] = l;
1373 else if (j == 17) /* 3 to 10 zero length codes */
1375 ZIPNEEDBITS(3)
1376 j = 3 + (b & 7);
1377 ZIPDUMPBITS(3)
1378 if ((cab_ULONG)i + j > n)
1379 return 1;
1380 while (j--)
1381 ll[i++] = 0;
1382 l = 0;
1384 else /* j == 18: 11 to 138 zero length codes */
1386 ZIPNEEDBITS(7)
1387 j = 11 + (b & 0x7f);
1388 ZIPDUMPBITS(7)
1389 if ((cab_ULONG)i + j > n)
1390 return 1;
1391 while (j--)
1392 ll[i++] = 0;
1393 l = 0;
1397 /* free decoding table for trees */
1398 fdi_Ziphuft_free(CAB(hfdi), tl);
1400 /* restore the global bit buffer */
1401 ZIP(bb) = b;
1402 ZIP(bk) = k;
1404 /* build the decoding tables for literal/length and distance codes */
1405 bl = ZIPLBITS;
1406 if((i = fdi_Ziphuft_build(ll, nl, 257, Zipcplens, Zipcplext, &tl, &bl, decomp_state)) != 0)
1408 if(i == 1)
1409 fdi_Ziphuft_free(CAB(hfdi), tl);
1410 return i; /* incomplete code set */
1412 bd = ZIPDBITS;
1413 fdi_Ziphuft_build(ll + nl, nd, 0, Zipcpdist, Zipcpdext, &td, &bd, decomp_state);
1415 /* decompress until an end-of-block code */
1416 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1417 return 1;
1419 /* free the decoding tables, return */
1420 fdi_Ziphuft_free(CAB(hfdi), tl);
1421 fdi_Ziphuft_free(CAB(hfdi), td);
1422 return 0;
1425 /*****************************************************
1426 * fdi_Zipinflate_block (internal)
1428 static cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1429 { /* decompress an inflated block */
1430 cab_ULONG t; /* block type */
1431 register cab_ULONG b; /* bit buffer */
1432 register cab_ULONG k; /* number of bits in bit buffer */
1434 /* make local bit buffer */
1435 b = ZIP(bb);
1436 k = ZIP(bk);
1438 /* read in last block bit */
1439 ZIPNEEDBITS(1)
1440 *e = (cab_LONG)b & 1;
1441 ZIPDUMPBITS(1)
1443 /* read in block type */
1444 ZIPNEEDBITS(2)
1445 t = b & 3;
1446 ZIPDUMPBITS(2)
1448 /* restore the global bit buffer */
1449 ZIP(bb) = b;
1450 ZIP(bk) = k;
1452 /* inflate that block type */
1453 if(t == 2)
1454 return fdi_Zipinflate_dynamic(decomp_state);
1455 if(t == 0)
1456 return fdi_Zipinflate_stored(decomp_state);
1457 if(t == 1)
1458 return fdi_Zipinflate_fixed(decomp_state);
1459 /* bad block type */
1460 return 2;
1463 /****************************************************
1464 * ZIPfdi_decomp(internal)
1466 static int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1468 cab_LONG e; /* last block flag */
1470 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1472 ZIP(inpos) = CAB(inbuf);
1473 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1474 if(outlen > ZIPWSIZE)
1475 return DECR_DATAFORMAT;
1477 /* CK = Chris Kirmse, official Microsoft purloiner */
1478 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1479 return DECR_ILLEGALDATA;
1480 ZIP(inpos) += 2;
1482 do {
1483 if(fdi_Zipinflate_block(&e, decomp_state))
1484 return DECR_ILLEGALDATA;
1485 } while(!e);
1487 /* return success */
1488 return DECR_OK;
1491 /*******************************************************************
1492 * QTMfdi_decomp(internal)
1494 static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1496 cab_UBYTE *inpos = CAB(inbuf);
1497 cab_UBYTE *window = QTM(window);
1498 cab_UBYTE *runsrc, *rundest;
1499 cab_ULONG window_posn = QTM(window_posn);
1500 cab_ULONG window_size = QTM(window_size);
1502 /* used by bitstream macros */
1503 register int bitsleft, bitrun, bitsneed;
1504 register cab_ULONG bitbuf;
1506 /* used by GET_SYMBOL */
1507 cab_ULONG range;
1508 cab_UWORD symf;
1509 int i;
1511 int extra, togo = outlen, match_length = 0, copy_length;
1512 cab_UBYTE selector, sym;
1513 cab_ULONG match_offset = 0;
1515 cab_UWORD H = 0xFFFF, L = 0, C;
1517 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1519 /* read initial value of C */
1520 Q_INIT_BITSTREAM;
1521 Q_READ_BITS(C, 16);
1523 /* apply 2^x-1 mask */
1524 window_posn &= window_size - 1;
1525 /* runs can't straddle the window wraparound */
1526 if ((window_posn + togo) > window_size) {
1527 TRACE("straddled run\n");
1528 return DECR_DATAFORMAT;
1531 while (togo > 0) {
1532 GET_SYMBOL(model7, selector);
1533 switch (selector) {
1534 case 0:
1535 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1536 break;
1537 case 1:
1538 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1539 break;
1540 case 2:
1541 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1542 break;
1543 case 3:
1544 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1545 break;
1547 case 4:
1548 /* selector 4 = fixed length of 3 */
1549 GET_SYMBOL(model4, sym);
1550 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1551 match_offset = CAB(q_position_base)[sym] + extra + 1;
1552 match_length = 3;
1553 break;
1555 case 5:
1556 /* selector 5 = fixed length of 4 */
1557 GET_SYMBOL(model5, sym);
1558 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1559 match_offset = CAB(q_position_base)[sym] + extra + 1;
1560 match_length = 4;
1561 break;
1563 case 6:
1564 /* selector 6 = variable length */
1565 GET_SYMBOL(model6len, sym);
1566 Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1567 match_length = CAB(q_length_base)[sym] + extra + 5;
1568 GET_SYMBOL(model6pos, sym);
1569 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1570 match_offset = CAB(q_position_base)[sym] + extra + 1;
1571 break;
1573 default:
1574 TRACE("Selector is bogus\n");
1575 return DECR_ILLEGALDATA;
1578 /* if this is a match */
1579 if (selector >= 4) {
1580 rundest = window + window_posn;
1581 togo -= match_length;
1583 /* copy any wrapped around source data */
1584 if (window_posn >= match_offset) {
1585 /* no wrap */
1586 runsrc = rundest - match_offset;
1587 } else {
1588 runsrc = rundest + (window_size - match_offset);
1589 copy_length = match_offset - window_posn;
1590 if (copy_length < match_length) {
1591 match_length -= copy_length;
1592 window_posn += copy_length;
1593 while (copy_length-- > 0) *rundest++ = *runsrc++;
1594 runsrc = window;
1597 window_posn += match_length;
1599 /* copy match data - no worries about destination wraps */
1600 while (match_length-- > 0) *rundest++ = *runsrc++;
1602 } /* while (togo > 0) */
1604 if (togo != 0) {
1605 TRACE("Frame overflow, this_run = %d\n", togo);
1606 return DECR_ILLEGALDATA;
1609 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1610 outlen, outlen);
1612 QTM(window_posn) = window_posn;
1613 return DECR_OK;
1616 /************************************************************
1617 * fdi_lzx_read_lens (internal)
1619 static int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1620 fdi_decomp_state *decomp_state) {
1621 cab_ULONG i,j, x,y;
1622 int z;
1624 register cab_ULONG bitbuf = lb->bb;
1625 register int bitsleft = lb->bl;
1626 cab_UBYTE *inpos = lb->ip;
1627 cab_UWORD *hufftbl;
1629 for (x = 0; x < 20; x++) {
1630 READ_BITS(y, 4);
1631 LENTABLE(PRETREE)[x] = y;
1633 BUILD_TABLE(PRETREE);
1635 for (x = first; x < last; ) {
1636 READ_HUFFSYM(PRETREE, z);
1637 if (z == 17) {
1638 READ_BITS(y, 4); y += 4;
1639 while (y--) lens[x++] = 0;
1641 else if (z == 18) {
1642 READ_BITS(y, 5); y += 20;
1643 while (y--) lens[x++] = 0;
1645 else if (z == 19) {
1646 READ_BITS(y, 1); y += 4;
1647 READ_HUFFSYM(PRETREE, z);
1648 z = lens[x] - z; if (z < 0) z += 17;
1649 while (y--) lens[x++] = z;
1651 else {
1652 z = lens[x] - z; if (z < 0) z += 17;
1653 lens[x++] = z;
1657 lb->bb = bitbuf;
1658 lb->bl = bitsleft;
1659 lb->ip = inpos;
1660 return 0;
1663 /*******************************************************
1664 * LZXfdi_decomp(internal)
1666 static int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1667 cab_UBYTE *inpos = CAB(inbuf);
1668 const cab_UBYTE *endinp = inpos + inlen;
1669 cab_UBYTE *window = LZX(window);
1670 cab_UBYTE *runsrc, *rundest;
1671 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1673 cab_ULONG window_posn = LZX(window_posn);
1674 cab_ULONG window_size = LZX(window_size);
1675 cab_ULONG R0 = LZX(R0);
1676 cab_ULONG R1 = LZX(R1);
1677 cab_ULONG R2 = LZX(R2);
1679 register cab_ULONG bitbuf;
1680 register int bitsleft;
1681 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1682 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1684 int togo = outlen, this_run, main_element, aligned_bits;
1685 int match_length, copy_length, length_footer, extra, verbatim_bits;
1687 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1689 INIT_BITSTREAM;
1691 /* read header if necessary */
1692 if (!LZX(header_read)) {
1693 i = j = 0;
1694 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1695 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1696 LZX(header_read) = 1;
1699 /* main decoding loop */
1700 while (togo > 0) {
1701 /* last block finished, new block expected */
1702 if (LZX(block_remaining) == 0) {
1703 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1704 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1705 INIT_BITSTREAM;
1708 READ_BITS(LZX(block_type), 3);
1709 READ_BITS(i, 16);
1710 READ_BITS(j, 8);
1711 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1713 switch (LZX(block_type)) {
1714 case LZX_BLOCKTYPE_ALIGNED:
1715 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1716 BUILD_TABLE(ALIGNED);
1717 /* rest of aligned header is same as verbatim */
1719 case LZX_BLOCKTYPE_VERBATIM:
1720 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1721 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1722 BUILD_TABLE(MAINTREE);
1723 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1725 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1726 BUILD_TABLE(LENGTH);
1727 break;
1729 case LZX_BLOCKTYPE_UNCOMPRESSED:
1730 LZX(intel_started) = 1; /* because we can't assume otherwise */
1731 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1732 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1733 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1734 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1735 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1736 break;
1738 default:
1739 return DECR_ILLEGALDATA;
1743 /* buffer exhaustion check */
1744 if (inpos > endinp) {
1745 /* it's possible to have a file where the next run is less than
1746 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1747 * in building the tables will exhaust the buffer, so we should
1748 * allow for this, but not allow those accidentally read bits to
1749 * be used (so we check that there are at least 16 bits
1750 * remaining - in this boundary case they aren't really part of
1751 * the compressed data)
1753 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1756 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1757 if (this_run > togo) this_run = togo;
1758 togo -= this_run;
1759 LZX(block_remaining) -= this_run;
1761 /* apply 2^x-1 mask */
1762 window_posn &= window_size - 1;
1763 /* runs can't straddle the window wraparound */
1764 if ((window_posn + this_run) > window_size)
1765 return DECR_DATAFORMAT;
1767 switch (LZX(block_type)) {
1769 case LZX_BLOCKTYPE_VERBATIM:
1770 while (this_run > 0) {
1771 READ_HUFFSYM(MAINTREE, main_element);
1773 if (main_element < LZX_NUM_CHARS) {
1774 /* literal: 0 to LZX_NUM_CHARS-1 */
1775 window[window_posn++] = main_element;
1776 this_run--;
1778 else {
1779 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1780 main_element -= LZX_NUM_CHARS;
1782 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1783 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1784 READ_HUFFSYM(LENGTH, length_footer);
1785 match_length += length_footer;
1787 match_length += LZX_MIN_MATCH;
1789 match_offset = main_element >> 3;
1791 if (match_offset > 2) {
1792 /* not repeated offset */
1793 if (match_offset != 3) {
1794 extra = CAB(extra_bits)[match_offset];
1795 READ_BITS(verbatim_bits, extra);
1796 match_offset = CAB(lzx_position_base)[match_offset]
1797 - 2 + verbatim_bits;
1799 else {
1800 match_offset = 1;
1803 /* update repeated offset LRU queue */
1804 R2 = R1; R1 = R0; R0 = match_offset;
1806 else if (match_offset == 0) {
1807 match_offset = R0;
1809 else if (match_offset == 1) {
1810 match_offset = R1;
1811 R1 = R0; R0 = match_offset;
1813 else /* match_offset == 2 */ {
1814 match_offset = R2;
1815 R2 = R0; R0 = match_offset;
1818 rundest = window + window_posn;
1819 this_run -= match_length;
1821 /* copy any wrapped around source data */
1822 if (window_posn >= match_offset) {
1823 /* no wrap */
1824 runsrc = rundest - match_offset;
1825 } else {
1826 runsrc = rundest + (window_size - match_offset);
1827 copy_length = match_offset - window_posn;
1828 if (copy_length < match_length) {
1829 match_length -= copy_length;
1830 window_posn += copy_length;
1831 while (copy_length-- > 0) *rundest++ = *runsrc++;
1832 runsrc = window;
1835 window_posn += match_length;
1837 /* copy match data - no worries about destination wraps */
1838 while (match_length-- > 0) *rundest++ = *runsrc++;
1841 break;
1843 case LZX_BLOCKTYPE_ALIGNED:
1844 while (this_run > 0) {
1845 READ_HUFFSYM(MAINTREE, main_element);
1847 if (main_element < LZX_NUM_CHARS) {
1848 /* literal: 0 to LZX_NUM_CHARS-1 */
1849 window[window_posn++] = main_element;
1850 this_run--;
1852 else {
1853 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1854 main_element -= LZX_NUM_CHARS;
1856 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1857 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1858 READ_HUFFSYM(LENGTH, length_footer);
1859 match_length += length_footer;
1861 match_length += LZX_MIN_MATCH;
1863 match_offset = main_element >> 3;
1865 if (match_offset > 2) {
1866 /* not repeated offset */
1867 extra = CAB(extra_bits)[match_offset];
1868 match_offset = CAB(lzx_position_base)[match_offset] - 2;
1869 if (extra > 3) {
1870 /* verbatim and aligned bits */
1871 extra -= 3;
1872 READ_BITS(verbatim_bits, extra);
1873 match_offset += (verbatim_bits << 3);
1874 READ_HUFFSYM(ALIGNED, aligned_bits);
1875 match_offset += aligned_bits;
1877 else if (extra == 3) {
1878 /* aligned bits only */
1879 READ_HUFFSYM(ALIGNED, aligned_bits);
1880 match_offset += aligned_bits;
1882 else if (extra > 0) { /* extra==1, extra==2 */
1883 /* verbatim bits only */
1884 READ_BITS(verbatim_bits, extra);
1885 match_offset += verbatim_bits;
1887 else /* extra == 0 */ {
1888 /* ??? */
1889 match_offset = 1;
1892 /* update repeated offset LRU queue */
1893 R2 = R1; R1 = R0; R0 = match_offset;
1895 else if (match_offset == 0) {
1896 match_offset = R0;
1898 else if (match_offset == 1) {
1899 match_offset = R1;
1900 R1 = R0; R0 = match_offset;
1902 else /* match_offset == 2 */ {
1903 match_offset = R2;
1904 R2 = R0; R0 = match_offset;
1907 rundest = window + window_posn;
1908 this_run -= match_length;
1910 /* copy any wrapped around source data */
1911 if (window_posn >= match_offset) {
1912 /* no wrap */
1913 runsrc = rundest - match_offset;
1914 } else {
1915 runsrc = rundest + (window_size - match_offset);
1916 copy_length = match_offset - window_posn;
1917 if (copy_length < match_length) {
1918 match_length -= copy_length;
1919 window_posn += copy_length;
1920 while (copy_length-- > 0) *rundest++ = *runsrc++;
1921 runsrc = window;
1924 window_posn += match_length;
1926 /* copy match data - no worries about destination wraps */
1927 while (match_length-- > 0) *rundest++ = *runsrc++;
1930 break;
1932 case LZX_BLOCKTYPE_UNCOMPRESSED:
1933 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1934 memcpy(window + window_posn, inpos, (size_t) this_run);
1935 inpos += this_run; window_posn += this_run;
1936 break;
1938 default:
1939 return DECR_ILLEGALDATA; /* might as well */
1945 if (togo != 0) return DECR_ILLEGALDATA;
1946 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1947 outlen, (size_t) outlen);
1949 LZX(window_posn) = window_posn;
1950 LZX(R0) = R0;
1951 LZX(R1) = R1;
1952 LZX(R2) = R2;
1954 /* intel E8 decoding */
1955 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1956 if (outlen <= 6 || !LZX(intel_started)) {
1957 LZX(intel_curpos) += outlen;
1959 else {
1960 cab_UBYTE *data = CAB(outbuf);
1961 cab_UBYTE *dataend = data + outlen - 10;
1962 cab_LONG curpos = LZX(intel_curpos);
1963 cab_LONG filesize = LZX(intel_filesize);
1964 cab_LONG abs_off, rel_off;
1966 LZX(intel_curpos) = curpos + outlen;
1968 while (data < dataend) {
1969 if (*data++ != 0xE8) { curpos++; continue; }
1970 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1971 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1972 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1973 data[0] = (cab_UBYTE) rel_off;
1974 data[1] = (cab_UBYTE) (rel_off >> 8);
1975 data[2] = (cab_UBYTE) (rel_off >> 16);
1976 data[3] = (cab_UBYTE) (rel_off >> 24);
1978 data += 4;
1979 curpos += 5;
1983 return DECR_OK;
1986 /**********************************************************
1987 * fdi_decomp (internal)
1989 * Decompress the requested number of bytes. If savemode is zero,
1990 * do not save the output anywhere, just plow through blocks until we
1991 * reach the specified (uncompressed) distance from the starting point,
1992 * and remember the position of the cabfile pointer (and which cabfile)
1993 * after we are done; otherwise, save the data out to CAB(filehf),
1994 * decompressing the requested number of bytes and writing them out. This
1995 * is also where we jump to additional cabinets in the case of split
1996 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1998 static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
1999 char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
2001 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
2002 cab_UBYTE buf[cfdata_SIZEOF], *data;
2003 cab_UWORD inlen, len, outlen, cando;
2004 cab_ULONG cksum;
2005 cab_LONG err;
2006 fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
2008 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
2010 while (bytes > 0) {
2011 /* cando = the max number of bytes we can do */
2012 cando = CAB(outlen);
2013 if (cando > bytes) cando = bytes;
2015 /* if cando != 0 */
2016 if (cando && savemode)
2017 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
2019 CAB(outpos) += cando;
2020 CAB(outlen) -= cando;
2021 bytes -= cando; if (!bytes) break;
2023 /* we only get here if we emptied the output buffer */
2025 /* read data header + data */
2026 inlen = outlen = 0;
2027 while (outlen == 0) {
2028 /* read the block header, skip the reserved part */
2029 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
2030 return DECR_INPUT;
2032 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
2033 return DECR_INPUT;
2035 /* we shouldn't get blocks over CAB_INPUTMAX in size */
2036 data = CAB(inbuf) + inlen;
2037 len = EndGetI16(buf+cfdata_CompressedSize);
2038 inlen += len;
2039 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
2040 if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
2041 return DECR_INPUT;
2043 /* clear two bytes after read-in data */
2044 data[len+1] = data[len+2] = 0;
2046 /* perform checksum test on the block (if one is stored) */
2047 cksum = EndGetI32(buf+cfdata_CheckSum);
2048 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
2049 return DECR_CHECKSUM; /* checksum is wrong */
2051 outlen = EndGetI16(buf+cfdata_UncompressedSize);
2053 /* outlen=0 means this block was the last contiguous part
2054 of a split block, continued in the next cabinet */
2055 if (outlen == 0) {
2056 int pathlen, filenamelen, idx, i;
2057 INT_PTR cabhf;
2058 char fullpath[MAX_PATH], userpath[256];
2059 FDINOTIFICATION fdin;
2060 FDICABINETINFO fdici;
2061 char emptystring = '\0';
2062 cab_UBYTE buf2[64];
2063 int success = FALSE;
2064 struct fdi_folder *fol = NULL, *linkfol = NULL;
2065 struct fdi_file *file = NULL, *linkfile = NULL;
2067 tryanothercab:
2069 /* set up the next decomp_state... */
2070 if (!(cab->next)) {
2071 if (!cab->mii.hasnext) return DECR_INPUT;
2073 if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
2074 return DECR_NOMEMORY;
2076 ZeroMemory(cab->next, sizeof(fdi_decomp_state));
2078 /* copy pszCabPath to userpath */
2079 ZeroMemory(userpath, 256);
2080 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2081 if (pathlen) {
2082 if (pathlen < 256) {
2083 for (i = 0; i <= pathlen; i++)
2084 userpath[i] = pszCabPath[i];
2085 } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2088 /* initial fdintNEXT_CABINET notification */
2089 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2090 fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
2091 fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
2092 fdin.psz3 = &userpath[0];
2093 fdin.fdie = FDIERROR_NONE;
2094 fdin.pv = pvUser;
2096 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2098 do {
2100 pathlen = strlen(userpath);
2101 filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
2103 /* slight overestimation here to save CPU cycles in the developer's brain */
2104 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2105 ERR("MAX_PATH exceeded.\n");
2106 return DECR_ILLEGALDATA;
2109 /* paste the path and filename together */
2110 idx = 0;
2111 if (pathlen) {
2112 for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
2113 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2115 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
2116 fullpath[idx] = '\0';
2118 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2120 /* try to get a handle to the cabfile */
2121 cabhf = PFDI_OPEN(CAB(hfdi), fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2122 if (cabhf == -1) {
2123 /* no file. allow the user to try again */
2124 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2125 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2126 continue;
2129 if (cabhf == 0) {
2130 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2131 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2132 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2133 continue;
2136 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2137 if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
2138 WARN("FDIIsCabinet failed.\n");
2139 PFDI_CLOSE(CAB(hfdi), cabhf);
2140 fdin.fdie = FDIERROR_NOT_A_CABINET;
2141 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2142 continue;
2145 if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
2146 WARN("Wrong Cabinet.\n");
2147 PFDI_CLOSE(CAB(hfdi), cabhf);
2148 fdin.fdie = FDIERROR_WRONG_CABINET;
2149 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2150 continue;
2153 break;
2155 } while (1);
2157 /* cabinet notification */
2158 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2159 fdin.setID = fdici.setID;
2160 fdin.iCabinet = fdici.iCabinet;
2161 fdin.pv = pvUser;
2162 fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2163 fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2164 fdin.psz3 = pszCabPath;
2166 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2168 cab->next->setID = fdici.setID;
2169 cab->next->iCabinet = fdici.iCabinet;
2170 cab->next->hfdi = CAB(hfdi);
2171 cab->next->filehf = CAB(filehf);
2172 cab->next->cabhf = cabhf;
2173 cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2175 cab = cab->next; /* advance to the next cabinet */
2177 /* read folders */
2178 for (i = 0; i < fdici.cFolders; i++) {
2179 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF)
2180 return DECR_INPUT;
2182 if (cab->mii.folder_resv > 0)
2183 PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2185 fol = PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2186 if (!fol) {
2187 ERR("out of memory!\n");
2188 return DECR_NOMEMORY;
2190 ZeroMemory(fol, sizeof(struct fdi_folder));
2191 if (!(cab->firstfol)) cab->firstfol = fol;
2193 fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2194 fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2195 fol->comp_type = EndGetI16(buf2+cffold_CompType);
2197 if (linkfol)
2198 linkfol->next = fol;
2199 linkfol = fol;
2202 /* read files */
2203 for (i = 0; i < fdici.cFiles; i++) {
2204 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2205 return DECR_INPUT;
2207 file = PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2208 if (!file) {
2209 ERR("out of memory!\n");
2210 return DECR_NOMEMORY;
2212 ZeroMemory(file, sizeof(struct fdi_file));
2213 if (!(cab->firstfile)) cab->firstfile = file;
2215 file->length = EndGetI32(buf2+cffile_UncompressedSize);
2216 file->offset = EndGetI32(buf2+cffile_FolderOffset);
2217 file->index = EndGetI16(buf2+cffile_FolderIndex);
2218 file->time = EndGetI16(buf2+cffile_Time);
2219 file->date = EndGetI16(buf2+cffile_Date);
2220 file->attribs = EndGetI16(buf2+cffile_Attribs);
2221 file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2223 if (!file->filename) return DECR_INPUT;
2225 if (linkfile)
2226 linkfile->next = file;
2227 linkfile = file;
2230 } else
2231 cab = cab->next; /* advance to the next cabinet */
2233 /* iterate files -- if we encounter the continued file, process it --
2234 otherwise, jump to the label above and keep looking */
2236 for (file = cab->firstfile; (file); file = file->next) {
2237 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2238 /* check to ensure a real match */
2239 if (lstrcmpiA(fi->filename, file->filename) == 0) {
2240 success = TRUE;
2241 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2242 return DECR_INPUT;
2243 break;
2247 if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2248 "Wrong Cabinet" notification? */
2252 /* decompress block */
2253 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2254 return err;
2255 CAB(outlen) = outlen;
2256 CAB(outpos) = CAB(outbuf);
2259 CAB(decomp_cab) = cab;
2260 return DECR_OK;
2263 static void free_decompression_temps(HFDI hfdi, const struct fdi_folder *fol,
2264 fdi_decomp_state *decomp_state)
2266 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2267 case cffoldCOMPTYPE_LZX:
2268 if (LZX(window)) {
2269 PFDI_FREE(hfdi, LZX(window));
2270 LZX(window) = NULL;
2272 break;
2273 case cffoldCOMPTYPE_QUANTUM:
2274 if (QTM(window)) {
2275 PFDI_FREE(hfdi, QTM(window));
2276 QTM(window) = NULL;
2278 break;
2282 static void free_decompression_mem(HFDI hfdi,
2283 fdi_decomp_state *decomp_state, struct fdi_file *file)
2285 struct fdi_folder *fol;
2286 while (decomp_state) {
2287 fdi_decomp_state *prev_fds;
2289 PFDI_CLOSE(hfdi, CAB(cabhf));
2291 /* free the storage remembered by mii */
2292 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2293 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2294 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2295 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2297 while (CAB(firstfol)) {
2298 fol = CAB(firstfol);
2299 CAB(firstfol) = CAB(firstfol)->next;
2300 PFDI_FREE(hfdi, fol);
2302 while (CAB(firstfile)) {
2303 file = CAB(firstfile);
2304 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2305 CAB(firstfile) = CAB(firstfile)->next;
2306 PFDI_FREE(hfdi, file);
2308 prev_fds = decomp_state;
2309 decomp_state = CAB(next);
2310 PFDI_FREE(hfdi, prev_fds);
2314 /***********************************************************************
2315 * FDICopy (CABINET.22)
2317 * Iterates through the files in the Cabinet file indicated by name and
2318 * file-location. May chain forward to additional cabinets (typically
2319 * only one) if files which begin in this Cabinet are continued in another
2320 * cabinet. For each file which is partially contained in this cabinet,
2321 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2322 * notification to the pfnfdin callback. For each file which begins in
2323 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2324 * callback, and the file is optionally decompressed and saved to disk.
2325 * Notification is not provided for files which are not at least partially
2326 * contained in the specified cabinet file.
2328 * See below for a thorough explanation of the various notification
2329 * callbacks.
2331 * PARAMS
2332 * hfdi [I] An HFDI from FDICreate
2333 * pszCabinet [I] C-style string containing the filename of the cabinet
2334 * pszCabPath [I] C-style string containing the file path of the cabinet
2335 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2336 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2337 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2338 * value: NULL.
2339 * pvUser [I] arbitrary void * value which is passed to callbacks.
2341 * RETURNS
2342 * TRUE if successful.
2343 * FALSE if unsuccessful (error information is provided in the ERF structure
2344 * associated with the provided decompression handle by FDICreate).
2346 * CALLBACKS
2348 * Two pointers to callback functions are provided as parameters to FDICopy:
2349 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2350 * types are as follows:
2352 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2353 * PFDINOTIFICATION pfdin );
2355 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2357 * You can create functions of this type using the FNFDINOTIFY() and
2358 * FNFDIDECRYPT() macros, respectively. For example:
2360 * FNFDINOTIFY(mycallback) {
2361 * / * use variables fdint and pfdin to process notification * /
2364 * The second callback, which could be used for decrypting encrypted data,
2365 * is not used at all.
2367 * Each notification informs the user of some event which has occurred during
2368 * decompression of the cabinet file; each notification is also an opportunity
2369 * for the callee to abort decompression. The information provided to the
2370 * callback and the meaning of the callback's return value vary drastically
2371 * across the various types of notification. The type of notification is the
2372 * fdint parameter; all other information is provided to the callback in
2373 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2374 * pfdin. The only part of that structure which is assigned for every callback
2375 * is the pv element, which contains the arbitrary value which was passed to
2376 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2377 * is highly dependent on fdint).
2379 * If you encounter unknown notifications, you should return zero if you want
2380 * decompression to continue (or -1 to abort). All strings used in the
2381 * callbacks are regular C-style strings. Detailed descriptions of each
2382 * notification type follow:
2384 * fdintCABINET_INFO:
2386 * This is the first notification provided after calling FDICopy, and provides
2387 * the user with various information about the cabinet. Note that this is
2388 * called for each cabinet FDICopy opens, not just the first one. In the
2389 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2390 * next cabinet file in the set after the one just loaded (if any), psz2
2391 * contains a pointer to the name or "info" of the next disk, psz3
2392 * contains a pointer to the file-path of the current cabinet, setID
2393 * contains an arbitrary constant associated with this set of cabinet files,
2394 * and iCabinet contains the numerical index of the current cabinet within
2395 * that set. Return zero, or -1 to abort.
2397 * fdintPARTIAL_FILE:
2399 * This notification is provided when FDICopy encounters a part of a file
2400 * contained in this cabinet which is missing its beginning. Files can be
2401 * split across cabinets, so this is not necessarily an abnormality; it just
2402 * means that the file in question begins in another cabinet. No file
2403 * corresponding to this notification is extracted from the cabinet. In the
2404 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2405 * partial file, psz2 contains a pointer to the file name of the cabinet in
2406 * which this file begins, and psz3 contains a pointer to the disk name or
2407 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2409 * fdintCOPY_FILE:
2411 * This notification is provided when FDICopy encounters a file which starts
2412 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2413 * look for files in cabinets after the first one). One notification will be
2414 * sent for each such file, before the file is decompressed. By returning
2415 * zero, the callback can instruct FDICopy to skip the file. In the structure
2416 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2417 * the size of the file (uncompressed), attribs contains the file attributes,
2418 * and date and time contain the date and time of the file. attributes, date,
2419 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2420 * for the entire cabinet, 0 to skip just this file but continue scanning the
2421 * cabinet for more files, or an FDIClose()-compatible file-handle.
2423 * fdintCLOSE_FILE_INFO:
2425 * This notification is important, don't forget to implement it. This
2426 * notification indicates that a file has been successfully uncompressed and
2427 * written to disk. Upon receipt of this notification, the callee is expected
2428 * to close the file handle, to set the attributes and date/time of the
2429 * closed file, and possibly to execute the file. In the structure pointed to
2430 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2431 * open file handle (close it), cb contains 1 or zero, indicating respectively
2432 * that the callee should or should not execute the file, and date, time
2433 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2434 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2435 * do so. Return TRUE, or FALSE to abort decompression.
2437 * fdintNEXT_CABINET:
2439 * This notification is called when FDICopy must load in another cabinet. This
2440 * can occur when a file's data is "split" across multiple cabinets. The
2441 * callee has the opportunity to request that FDICopy look in a different file
2442 * path for the specified cabinet file, by writing that data into a provided
2443 * buffer (see below for more information). This notification will be received
2444 * more than once per-cabinet in the instance that FDICopy failed to find a
2445 * valid cabinet at the location specified by the first per-cabinet
2446 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2447 * structure pointed to by pfdin indicates the error which prevented FDICopy
2448 * from proceeding successfully. Return zero to indicate success, or -1 to
2449 * indicate failure and abort FDICopy.
2451 * Upon receipt of this notification, the structure pointed to by pfdin will
2452 * contain the following values: psz1 pointing to the name of the cabinet
2453 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2454 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2455 * and fdie containing either FDIERROR_NONE, or one of the following:
2457 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2458 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2459 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2460 * FDIERROR_WRONG_CABINET.
2462 * The callee may choose to change the path where FDICopy will look for the
2463 * cabinet after this notification. To do so, the caller may write the new
2464 * pathname to the buffer pointed to by psz3, which is 256 characters in
2465 * length, including the terminating null character, before returning zero.
2467 * fdintENUMERATE:
2469 * Undocumented and unimplemented in wine, this seems to be sent each time
2470 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2471 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2472 * provides information about the current cabinet instead of the next one....
2473 * this is just a guess, it has not been looked at closely.
2475 * INCLUDES
2476 * fdi.c
2478 BOOL __cdecl FDICopy(
2479 HFDI hfdi,
2480 char *pszCabinet,
2481 char *pszCabPath,
2482 int flags,
2483 PFNFDINOTIFY pfnfdin,
2484 PFNFDIDECRYPT pfnfdid,
2485 void *pvUser)
2487 FDICABINETINFO fdici;
2488 FDINOTIFICATION fdin;
2489 INT_PTR cabhf, filehf = 0;
2490 int idx;
2491 unsigned int i;
2492 char fullpath[MAX_PATH];
2493 size_t pathlen, filenamelen;
2494 char emptystring = '\0';
2495 cab_UBYTE buf[64];
2496 struct fdi_folder *fol = NULL, *linkfol = NULL;
2497 struct fdi_file *file = NULL, *linkfile = NULL;
2498 fdi_decomp_state *decomp_state;
2500 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, "
2501 "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2502 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2504 if (!REALLY_IS_FDI(hfdi)) {
2505 SetLastError(ERROR_INVALID_HANDLE);
2506 return FALSE;
2509 if (!(decomp_state = PFDI_ALLOC(hfdi, sizeof(fdi_decomp_state))))
2511 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2512 return FALSE;
2514 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2516 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2517 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2519 /* slight overestimation here to save CPU cycles in the developer's brain */
2520 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2521 ERR("MAX_PATH exceeded.\n");
2522 PFDI_FREE(hfdi, decomp_state);
2523 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2524 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2525 PFDI_INT(hfdi)->perf->fError = TRUE;
2526 SetLastError(ERROR_FILE_NOT_FOUND);
2527 return FALSE;
2530 /* paste the path and filename together */
2531 idx = 0;
2532 if (pathlen) {
2533 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2534 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2536 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2537 fullpath[idx] = '\0';
2539 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2541 /* get a handle to the cabfile */
2542 cabhf = PFDI_OPEN(hfdi, fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2543 if (cabhf == -1) {
2544 PFDI_FREE(hfdi, decomp_state);
2545 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2546 PFDI_INT(hfdi)->perf->fError = TRUE;
2547 SetLastError(ERROR_FILE_NOT_FOUND);
2548 return FALSE;
2551 if (cabhf == 0) {
2552 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2553 PFDI_FREE(hfdi, decomp_state);
2554 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2555 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2556 PFDI_INT(hfdi)->perf->fError = TRUE;
2557 SetLastError(ERROR_FILE_NOT_FOUND);
2558 return FALSE;
2561 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2562 if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2563 ERR("FDIIsCabinet failed.\n");
2564 PFDI_FREE(hfdi, decomp_state);
2565 PFDI_CLOSE(hfdi, cabhf);
2566 return FALSE;
2569 /* cabinet notification */
2570 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2571 fdin.setID = fdici.setID;
2572 fdin.iCabinet = fdici.iCabinet;
2573 fdin.pv = pvUser;
2574 fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2575 fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2576 fdin.psz3 = pszCabPath;
2578 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2579 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2580 PFDI_INT(hfdi)->perf->erfType = 0;
2581 PFDI_INT(hfdi)->perf->fError = TRUE;
2582 goto bail_and_fail;
2585 CAB(setID) = fdici.setID;
2586 CAB(iCabinet) = fdici.iCabinet;
2587 CAB(cabhf) = cabhf;
2589 /* read folders */
2590 for (i = 0; i < fdici.cFolders; i++) {
2591 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2592 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2593 PFDI_INT(hfdi)->perf->erfType = 0;
2594 PFDI_INT(hfdi)->perf->fError = TRUE;
2595 goto bail_and_fail;
2598 if (CAB(mii).folder_resv > 0)
2599 PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2601 fol = PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2602 if (!fol) {
2603 ERR("out of memory!\n");
2604 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2605 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2606 PFDI_INT(hfdi)->perf->fError = TRUE;
2607 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2608 goto bail_and_fail;
2610 ZeroMemory(fol, sizeof(struct fdi_folder));
2611 if (!CAB(firstfol)) CAB(firstfol) = fol;
2613 fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2614 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2615 fol->comp_type = EndGetI16(buf+cffold_CompType);
2617 if (linkfol)
2618 linkfol->next = fol;
2619 linkfol = fol;
2622 /* read files */
2623 for (i = 0; i < fdici.cFiles; i++) {
2624 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2625 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2626 PFDI_INT(hfdi)->perf->erfType = 0;
2627 PFDI_INT(hfdi)->perf->fError = TRUE;
2628 goto bail_and_fail;
2631 file = PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2632 if (!file) {
2633 ERR("out of memory!\n");
2634 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2635 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2636 PFDI_INT(hfdi)->perf->fError = TRUE;
2637 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2638 goto bail_and_fail;
2640 ZeroMemory(file, sizeof(struct fdi_file));
2641 if (!CAB(firstfile)) CAB(firstfile) = file;
2643 file->length = EndGetI32(buf+cffile_UncompressedSize);
2644 file->offset = EndGetI32(buf+cffile_FolderOffset);
2645 file->index = EndGetI16(buf+cffile_FolderIndex);
2646 file->time = EndGetI16(buf+cffile_Time);
2647 file->date = EndGetI16(buf+cffile_Date);
2648 file->attribs = EndGetI16(buf+cffile_Attribs);
2649 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2651 if (!file->filename) {
2652 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2653 PFDI_INT(hfdi)->perf->erfType = 0;
2654 PFDI_INT(hfdi)->perf->fError = TRUE;
2655 goto bail_and_fail;
2658 if (linkfile)
2659 linkfile->next = file;
2660 linkfile = file;
2663 for (file = CAB(firstfile); (file); file = file->next) {
2666 * FIXME: This implementation keeps multiple cabinet files open at once
2667 * when encountering a split cabinet. It is a quirk of this implementation
2668 * that sometimes we decrypt the same block of data more than once, to find
2669 * the right starting point for a file, moving the file-pointer backwards.
2670 * If we kept a cache of certain file-pointer information, we could eliminate
2671 * that behavior... in fact I am not sure that the caching we already have
2672 * is not sufficient.
2674 * The current implementation seems to work fine in straightforward situations
2675 * where all the cabinet files needed for decryption are simultaneously
2676 * available. But presumably, the API is supposed to support cabinets which
2677 * are split across multiple CDROMS; we may need to change our implementation
2678 * to strictly serialize it's file usage so that it opens only one cabinet
2679 * at a time. Some experimentation with Windows is needed to figure out the
2680 * precise semantics required. The relevant code is here and in fdi_decomp().
2683 /* partial-file notification */
2684 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2686 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2687 * and perform some tests to figure out the right behavior. The SDK says
2688 * FDICopy will notify the user of the filename and "disk name" (info) of
2689 * the cabinet where the spanning file /started/.
2691 * That would certainly be convenient for the API-user, who could abort,
2692 * everything (or parallelize, if that's allowed (it is in wine)), and call
2693 * FDICopy again with the provided filename, so as to avoid partial file
2694 * notification and successfully unpack. This task could be quite unpleasant
2695 * from wine's perspective: the information specifying the "start cabinet" for
2696 * a file is associated nowhere with the file header and is not to be found in
2697 * the cabinet header. We have only the index of the cabinet wherein the folder
2698 * begins, which contains the file. To find that cabinet, we must consider the
2699 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2700 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2701 * list).
2703 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2704 * cabinet other than the active one might be at another filepath than the
2705 * current one, or on another CDROM. This could get rather dicey, especially
2706 * if we imagine parallelized access to the FDICopy API.
2708 * The current implementation punts -- it just returns the previous cabinet and
2709 * it's info from the header of this cabinet. This provides the right answer in
2710 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2711 * we "fix" it.
2713 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2714 fdin.pv = pvUser;
2715 fdin.psz1 = (char *)file->filename;
2716 fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2717 fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2719 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2720 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2721 PFDI_INT(hfdi)->perf->erfType = 0;
2722 PFDI_INT(hfdi)->perf->fError = TRUE;
2723 goto bail_and_fail;
2725 /* I don't think we are supposed to decompress partial files. This prevents it. */
2726 file->oppressed = TRUE;
2728 if (file->oppressed) {
2729 filehf = 0;
2730 } else {
2731 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2732 fdin.pv = pvUser;
2733 fdin.psz1 = (char *)file->filename;
2734 fdin.cb = file->length;
2735 fdin.date = file->date;
2736 fdin.time = file->time;
2737 fdin.attribs = file->attribs;
2738 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2739 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2740 PFDI_INT(hfdi)->perf->erfType = 0;
2741 PFDI_INT(hfdi)->perf->fError = TRUE;
2742 filehf = 0;
2743 goto bail_and_fail;
2747 /* find the folder for this file if necc. */
2748 if (filehf) {
2749 int i2;
2751 fol = CAB(firstfol);
2752 if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2753 /* pick the last folder */
2754 while (fol->next) fol = fol->next;
2755 } else {
2756 for (i2 = 0; (i2 < file->index); i2++)
2757 if (fol->next) /* bug resistance, should always be true */
2758 fol = fol->next;
2762 if (filehf) {
2763 cab_UWORD comptype = fol->comp_type;
2764 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2765 int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2766 int err = 0;
2768 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2770 /* set up decomp_state */
2771 CAB(hfdi) = hfdi;
2772 CAB(filehf) = filehf;
2774 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2775 if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2777 TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2779 /* free stuff for the old decompresser */
2780 switch (ct2) {
2781 case cffoldCOMPTYPE_LZX:
2782 if (LZX(window)) {
2783 PFDI_FREE(hfdi, LZX(window));
2784 LZX(window) = NULL;
2786 break;
2787 case cffoldCOMPTYPE_QUANTUM:
2788 if (QTM(window)) {
2789 PFDI_FREE(hfdi, QTM(window));
2790 QTM(window) = NULL;
2792 break;
2795 CAB(decomp_cab) = NULL;
2796 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2797 CAB(offset) = 0;
2798 CAB(outlen) = 0;
2800 /* initialize the new decompresser */
2801 switch (ct1) {
2802 case cffoldCOMPTYPE_NONE:
2803 CAB(decompress) = NONEfdi_decomp;
2804 break;
2805 case cffoldCOMPTYPE_MSZIP:
2806 CAB(decompress) = ZIPfdi_decomp;
2807 break;
2808 case cffoldCOMPTYPE_QUANTUM:
2809 CAB(decompress) = QTMfdi_decomp;
2810 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2811 break;
2812 case cffoldCOMPTYPE_LZX:
2813 CAB(decompress) = LZXfdi_decomp;
2814 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2815 break;
2816 default:
2817 err = DECR_DATAFORMAT;
2821 CAB(current) = fol;
2823 switch (err) {
2824 case DECR_OK:
2825 break;
2826 case DECR_NOMEMORY:
2827 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2828 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2829 PFDI_INT(hfdi)->perf->fError = TRUE;
2830 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2831 goto bail_and_fail;
2832 default:
2833 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2834 PFDI_INT(hfdi)->perf->erfOper = 0;
2835 PFDI_INT(hfdi)->perf->fError = TRUE;
2836 goto bail_and_fail;
2839 if (file->offset > CAB(offset)) {
2840 /* decode bytes and send them to /dev/null */
2841 switch (fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser)) {
2842 case DECR_OK:
2843 break;
2844 case DECR_USERABORT:
2845 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2846 PFDI_INT(hfdi)->perf->erfType = 0;
2847 PFDI_INT(hfdi)->perf->fError = TRUE;
2848 goto bail_and_fail;
2849 case DECR_NOMEMORY:
2850 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2851 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2852 PFDI_INT(hfdi)->perf->fError = TRUE;
2853 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2854 goto bail_and_fail;
2855 default:
2856 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2857 PFDI_INT(hfdi)->perf->erfOper = 0;
2858 PFDI_INT(hfdi)->perf->fError = TRUE;
2859 goto bail_and_fail;
2861 CAB(offset) = file->offset;
2864 /* now do the actual decompression */
2865 err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2866 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2868 /* fdintCLOSE_FILE_INFO notification */
2869 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2870 fdin.pv = pvUser;
2871 fdin.psz1 = (char *)file->filename;
2872 fdin.hf = filehf;
2873 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2874 fdin.date = file->date;
2875 fdin.time = file->time;
2876 fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2877 ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2878 filehf = 0;
2880 switch (err) {
2881 case DECR_OK:
2882 break;
2883 case DECR_USERABORT:
2884 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2885 PFDI_INT(hfdi)->perf->erfType = 0;
2886 PFDI_INT(hfdi)->perf->fError = TRUE;
2887 goto bail_and_fail;
2888 case DECR_NOMEMORY:
2889 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2890 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2891 PFDI_INT(hfdi)->perf->fError = TRUE;
2892 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2893 goto bail_and_fail;
2894 default:
2895 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2896 PFDI_INT(hfdi)->perf->erfOper = 0;
2897 PFDI_INT(hfdi)->perf->fError = TRUE;
2898 goto bail_and_fail;
2903 free_decompression_temps(hfdi, fol, decomp_state);
2904 free_decompression_mem(hfdi, decomp_state, file);
2906 return TRUE;
2908 bail_and_fail: /* here we free ram before error returns */
2910 if (fol) free_decompression_temps(hfdi, fol, decomp_state);
2912 if (filehf) PFDI_CLOSE(hfdi, filehf);
2914 free_decompression_mem(hfdi, decomp_state, file);
2916 return FALSE;
2919 /***********************************************************************
2920 * FDIDestroy (CABINET.23)
2922 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2923 * of FDICopy. Only reason for failure would be an invalid handle.
2925 * PARAMS
2926 * hfdi [I] The HFDI to free
2928 * RETURNS
2929 * TRUE for success
2930 * FALSE for failure
2932 BOOL __cdecl FDIDestroy(HFDI hfdi)
2934 TRACE("(hfdi == ^%p)\n", hfdi);
2935 if (REALLY_IS_FDI(hfdi)) {
2936 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2937 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2938 return TRUE;
2939 } else {
2940 SetLastError(ERROR_INVALID_HANDLE);
2941 return FALSE;
2945 /***********************************************************************
2946 * FDITruncateCabinet (CABINET.24)
2948 * Removes all folders of a cabinet file after and including the
2949 * specified folder number.
2951 * PARAMS
2952 * hfdi [I] Handle to the FDI context.
2953 * pszCabinetName [I] Filename of the cabinet.
2954 * iFolderToDelete [I] Index of the first folder to delete.
2956 * RETURNS
2957 * Success: TRUE.
2958 * Failure: FALSE.
2960 * NOTES
2961 * The PFNWRITE function supplied to FDICreate must truncate the
2962 * file at the current position if the number of bytes to write is 0.
2964 BOOL __cdecl FDITruncateCabinet(
2965 HFDI hfdi,
2966 char *pszCabinetName,
2967 USHORT iFolderToDelete)
2969 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2970 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2972 if (!REALLY_IS_FDI(hfdi)) {
2973 SetLastError(ERROR_INVALID_HANDLE);
2974 return FALSE;
2977 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2978 return FALSE;