cabinet: Fix the regression caused by 4046075462c00f4479f185d1c0514584ff851223.
[wine/multimedia.git] / dlls / cabinet / fdi.c
blob47e36e826cafcb2c95e88a75873e6d9250f6e7c7
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 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 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 int make_decode_table(cab_ULONG nsyms, cab_ULONG nbits, const cab_UBYTE *length, cab_UWORD *table) {
224 register cab_UWORD sym;
225 register cab_ULONG leaf;
226 register cab_UBYTE bit_num = 1;
227 cab_ULONG fill;
228 cab_ULONG pos = 0; /* the current position in the decode table */
229 cab_ULONG table_mask = 1 << nbits;
230 cab_ULONG bit_mask = table_mask >> 1; /* don't do 0 length codes */
231 cab_ULONG next_symbol = bit_mask; /* base of allocation for long codes */
233 /* fill entries for codes short enough for a direct mapping */
234 while (bit_num <= nbits) {
235 for (sym = 0; sym < nsyms; sym++) {
236 if (length[sym] == bit_num) {
237 leaf = pos;
239 if((pos += bit_mask) > table_mask) return 1; /* table overrun */
241 /* fill all possible lookups of this symbol with the symbol itself */
242 fill = bit_mask;
243 while (fill-- > 0) table[leaf++] = sym;
246 bit_mask >>= 1;
247 bit_num++;
250 /* if there are any codes longer than nbits */
251 if (pos != table_mask) {
252 /* clear the remainder of the table */
253 for (sym = pos; sym < table_mask; sym++) table[sym] = 0;
255 /* give ourselves room for codes to grow by up to 16 more bits */
256 pos <<= 16;
257 table_mask <<= 16;
258 bit_mask = 1 << 15;
260 while (bit_num <= 16) {
261 for (sym = 0; sym < nsyms; sym++) {
262 if (length[sym] == bit_num) {
263 leaf = pos >> 16;
264 for (fill = 0; fill < bit_num - nbits; fill++) {
265 /* if this path hasn't been taken yet, 'allocate' two entries */
266 if (table[leaf] == 0) {
267 table[(next_symbol << 1)] = 0;
268 table[(next_symbol << 1) + 1] = 0;
269 table[leaf] = next_symbol++;
271 /* follow the path and select either left or right for next bit */
272 leaf = table[leaf] << 1;
273 if ((pos >> (15-fill)) & 1) leaf++;
275 table[leaf] = sym;
277 if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
280 bit_mask >>= 1;
281 bit_num++;
285 /* full table? */
286 if (pos == table_mask) return 0;
288 /* either erroneous table, or all elements are 0 - let's find out. */
289 for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1;
290 return 0;
293 /*************************************************************************
294 * checksum (internal)
296 cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum) {
297 int len;
298 cab_ULONG ul = 0;
300 for (len = bytes >> 2; len--; data += 4) {
301 csum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
304 switch (bytes & 3) {
305 case 3: ul |= *data++ << 16;
306 case 2: ul |= *data++ << 8;
307 case 1: ul |= *data;
309 csum ^= ul;
311 return csum;
314 /***********************************************************************
315 * FDICreate (CABINET.20)
317 * Provided with several callbacks (all of them are mandatory),
318 * returns a handle which can be used to perform operations
319 * on cabinet files.
321 * PARAMS
322 * pfnalloc [I] A pointer to a function which allocates ram. Uses
323 * the same interface as malloc.
324 * pfnfree [I] A pointer to a function which frees ram. Uses the
325 * same interface as free.
326 * pfnopen [I] A pointer to a function which opens a file. Uses
327 * the same interface as _open.
328 * pfnread [I] A pointer to a function which reads from a file into
329 * a caller-provided buffer. Uses the same interface
330 * as _read
331 * pfnwrite [I] A pointer to a function which writes to a file from
332 * a caller-provided buffer. Uses the same interface
333 * as _write.
334 * pfnclose [I] A pointer to a function which closes a file handle.
335 * Uses the same interface as _close.
336 * pfnseek [I] A pointer to a function which seeks in a file.
337 * Uses the same interface as _lseek.
338 * cpuType [I] The type of CPU; ignored in wine (recommended value:
339 * cpuUNKNOWN, aka -1).
340 * perf [IO] A pointer to an ERF structure. When FDICreate
341 * returns an error condition, error information may
342 * be found here as well as from GetLastError.
344 * RETURNS
345 * On success, returns an FDI handle of type HFDI.
346 * On failure, the NULL file handle is returned. Error
347 * info can be retrieved from perf.
349 * INCLUDES
350 * fdi.h
353 HFDI __cdecl FDICreate(
354 PFNALLOC pfnalloc,
355 PFNFREE pfnfree,
356 PFNOPEN pfnopen,
357 PFNREAD pfnread,
358 PFNWRITE pfnwrite,
359 PFNCLOSE pfnclose,
360 PFNSEEK pfnseek,
361 int cpuType,
362 PERF perf)
364 HFDI rv;
366 TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, "
367 "pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
368 pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
369 cpuType, perf);
371 if ((!pfnalloc) || (!pfnfree)) {
372 perf->erfOper = FDIERROR_NONE;
373 perf->erfType = ERROR_BAD_ARGUMENTS;
374 perf->fError = TRUE;
376 SetLastError(ERROR_BAD_ARGUMENTS);
377 return NULL;
380 if (!((rv = (*pfnalloc)(sizeof(FDI_Int))))) {
381 perf->erfOper = FDIERROR_ALLOC_FAIL;
382 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
383 perf->fError = TRUE;
385 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
386 return NULL;
389 PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
390 PFDI_INT(rv)->pfnalloc = pfnalloc;
391 PFDI_INT(rv)->pfnfree = pfnfree;
392 PFDI_INT(rv)->pfnopen = pfnopen;
393 PFDI_INT(rv)->pfnread = pfnread;
394 PFDI_INT(rv)->pfnwrite = pfnwrite;
395 PFDI_INT(rv)->pfnclose = pfnclose;
396 PFDI_INT(rv)->pfnseek = pfnseek;
397 /* no-brainer: we ignore the cpu type; this is only used
398 for the 16-bit versions in Windows anyhow... */
399 PFDI_INT(rv)->perf = perf;
401 return rv;
404 /*******************************************************************
405 * FDI_getoffset (internal)
407 * returns the file pointer position of a file handle.
409 static long FDI_getoffset(HFDI hfdi, INT_PTR hf)
411 return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
414 /**********************************************************************
415 * FDI_read_string (internal)
417 * allocate and read an arbitrarily long string from the cabinet
419 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
421 size_t len=256,
422 base = FDI_getoffset(hfdi, hf),
423 maxlen = cabsize - base;
424 BOOL ok = FALSE;
425 unsigned int i;
426 cab_UBYTE *buf = NULL;
428 TRACE("(hfdi == ^%p, hf == %ld, cabsize == %ld)\n", hfdi, hf, cabsize);
430 do {
431 if (len > maxlen) len = maxlen;
432 if (!(buf = PFDI_ALLOC(hfdi, len))) break;
433 if (!PFDI_READ(hfdi, hf, buf, len)) break;
435 /* search for a null terminator in what we've just read */
436 for (i=0; i < len; i++) {
437 if (!buf[i]) {ok=TRUE; break;}
440 if (!ok) {
441 if (len == maxlen) {
442 ERR("cabinet is truncated\n");
443 break;
445 /* The buffer is too small for the string. Reset the file to the point
446 * were we started, free the buffer and increase the size for the next try
448 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
449 PFDI_FREE(hfdi, buf);
450 buf = NULL;
451 len *= 2;
453 } while (!ok);
455 if (!ok) {
456 if (buf)
457 PFDI_FREE(hfdi, buf);
458 else
459 ERR("out of memory!\n");
460 return NULL;
463 /* otherwise, set the stream to just after the string and return */
464 PFDI_SEEK(hfdi, hf, base + strlen((char *)buf) + 1, SEEK_SET);
466 return (char *) buf;
469 /******************************************************************
470 * FDI_read_entries (internal)
472 * process the cabinet header in the style of FDIIsCabinet, but
473 * without the sanity checks (and bug)
475 static BOOL FDI_read_entries(
476 HFDI hfdi,
477 INT_PTR hf,
478 PFDICABINETINFO pfdici,
479 PMORE_ISCAB_INFO pmii)
481 int num_folders, num_files, header_resv, folder_resv = 0;
482 LONG base_offset, cabsize;
483 USHORT setid, cabidx, flags;
484 cab_UBYTE buf[64], block_resv;
485 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
487 TRACE("(hfdi == ^%p, hf == %ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
490 * FIXME: I just noticed that I am memorizing the initial file pointer
491 * offset and restoring it before reading in the rest of the header
492 * information in the cabinet. Perhaps that's correct -- that is, perhaps
493 * this API is supposed to support "streaming" cabinets which are embedded
494 * in other files, or cabinets which begin at file offsets other than zero.
495 * Otherwise, I should instead go to the absolute beginning of the file.
496 * (Either way, the semantics of wine's FDICopy require me to leave the
497 * file pointer where it is afterwards -- If Windows does not do so, we
498 * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
500 * So, the answer lies in Windows; will native cabinet.dll recognize a
501 * cabinet "file" embedded in another file? Note that cabextract.c does
502 * support this, which implies that Microsoft's might. I haven't tried it
503 * yet so I don't know. ATM, most of wine's FDI cabinet routines (except
504 * this one) would not work in this way. To fix it, we could just make the
505 * various references to absolute file positions in the code relative to an
506 * initial "beginning" offset. Because the FDICopy API doesn't take a
507 * file-handle like this one, we would therein need to search through the
508 * file for the beginning of the cabinet (as we also do in cabextract.c).
509 * Note that this limits us to a maximum of one cabinet per. file: the first.
511 * So, in summary: either the code below is wrong, or the rest of fdi.c is
512 * wrong... I cannot imagine that both are correct ;) One of these flaws
513 * should be fixed after determining the behavior on Windows. We ought
514 * to check both FDIIsCabinet and FDICopy for the right behavior.
516 * -gmt
519 /* get basic offset & size info */
520 base_offset = FDI_getoffset(hfdi, hf);
522 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
523 if (pmii) {
524 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
525 PFDI_INT(hfdi)->perf->erfType = 0;
526 PFDI_INT(hfdi)->perf->fError = TRUE;
528 return FALSE;
531 cabsize = FDI_getoffset(hfdi, hf);
533 if ((cabsize == -1) || (base_offset == -1) ||
534 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
535 if (pmii) {
536 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
537 PFDI_INT(hfdi)->perf->erfType = 0;
538 PFDI_INT(hfdi)->perf->fError = TRUE;
540 return FALSE;
543 /* read in the CFHEADER */
544 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
545 if (pmii) {
546 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
547 PFDI_INT(hfdi)->perf->erfType = 0;
548 PFDI_INT(hfdi)->perf->fError = TRUE;
550 return FALSE;
553 /* check basic MSCF signature */
554 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
555 if (pmii) {
556 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
557 PFDI_INT(hfdi)->perf->erfType = 0;
558 PFDI_INT(hfdi)->perf->fError = TRUE;
560 return FALSE;
563 /* get the number of folders */
564 num_folders = EndGetI16(buf+cfhead_NumFolders);
565 if (num_folders == 0) {
566 /* PONDERME: is this really invalid? */
567 WARN("weird cabinet detect failure: no folders in cabinet\n");
568 if (pmii) {
569 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
570 PFDI_INT(hfdi)->perf->erfType = 0;
571 PFDI_INT(hfdi)->perf->fError = TRUE;
573 return FALSE;
576 /* get the number of files */
577 num_files = EndGetI16(buf+cfhead_NumFiles);
578 if (num_files == 0) {
579 /* PONDERME: is this really invalid? */
580 WARN("weird cabinet detect failure: no files in cabinet\n");
581 if (pmii) {
582 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
583 PFDI_INT(hfdi)->perf->erfType = 0;
584 PFDI_INT(hfdi)->perf->fError = TRUE;
586 return FALSE;
589 /* setid */
590 setid = EndGetI16(buf+cfhead_SetID);
592 /* cabinet (set) index */
593 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
595 /* check the header revision */
596 if ((buf[cfhead_MajorVersion] > 1) ||
597 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
599 WARN("cabinet format version > 1.3\n");
600 if (pmii) {
601 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
602 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
603 PFDI_INT(hfdi)->perf->fError = TRUE;
605 return FALSE;
608 /* pull the flags out */
609 flags = EndGetI16(buf+cfhead_Flags);
611 /* read the reserved-sizes part of header, if present */
612 if (flags & cfheadRESERVE_PRESENT) {
613 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
614 ERR("bunk reserve-sizes?\n");
615 if (pmii) {
616 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
617 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
618 PFDI_INT(hfdi)->perf->fError = TRUE;
620 return FALSE;
623 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
624 if (pmii) pmii->header_resv = header_resv;
625 folder_resv = buf[cfheadext_FolderReserved];
626 if (pmii) pmii->folder_resv = folder_resv;
627 block_resv = buf[cfheadext_DataReserved];
628 if (pmii) pmii->block_resv = block_resv;
630 if (header_resv > 60000) {
631 WARN("WARNING; header reserved space > 60000\n");
634 /* skip the reserved header */
635 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
636 ERR("seek failure: header_resv\n");
637 if (pmii) {
638 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
639 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
640 PFDI_INT(hfdi)->perf->fError = TRUE;
642 return FALSE;
646 if (flags & cfheadPREV_CABINET) {
647 prevname = FDI_read_string(hfdi, hf, cabsize);
648 if (!prevname) {
649 if (pmii) {
650 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
651 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
652 PFDI_INT(hfdi)->perf->fError = TRUE;
654 return FALSE;
655 } else
656 if (pmii)
657 pmii->prevname = prevname;
658 else
659 PFDI_FREE(hfdi, prevname);
660 previnfo = FDI_read_string(hfdi, hf, cabsize);
661 if (previnfo) {
662 if (pmii)
663 pmii->previnfo = previnfo;
664 else
665 PFDI_FREE(hfdi, previnfo);
669 if (flags & cfheadNEXT_CABINET) {
670 if (pmii)
671 pmii->hasnext = TRUE;
672 nextname = FDI_read_string(hfdi, hf, cabsize);
673 if (!nextname) {
674 if ((flags & cfheadPREV_CABINET) && pmii) {
675 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
676 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
678 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
679 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
680 PFDI_INT(hfdi)->perf->fError = TRUE;
681 return FALSE;
682 } else
683 if (pmii)
684 pmii->nextname = nextname;
685 else
686 PFDI_FREE(hfdi, nextname);
687 nextinfo = FDI_read_string(hfdi, hf, cabsize);
688 if (nextinfo) {
689 if (pmii)
690 pmii->nextinfo = nextinfo;
691 else
692 PFDI_FREE(hfdi, nextinfo);
696 /* we could process the whole cabinet searching for problems;
697 instead lets stop here. Now let's fill out the paperwork */
698 pfdici->cbCabinet = cabsize;
699 pfdici->cFolders = num_folders;
700 pfdici->cFiles = num_files;
701 pfdici->setID = setid;
702 pfdici->iCabinet = cabidx;
703 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
704 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
705 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
706 return TRUE;
709 /***********************************************************************
710 * FDIIsCabinet (CABINET.21)
712 * Informs the caller as to whether or not the provided file handle is
713 * really a cabinet or not, filling out the provided PFDICABINETINFO
714 * structure with information about the cabinet. Brief explanations of
715 * the elements of this structure are available as comments accompanying
716 * its definition in wine's include/fdi.h.
718 * PARAMS
719 * hfdi [I] An HFDI from FDICreate
720 * hf [I] The file handle about which the caller inquires
721 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
722 * be filled out with information about the cabinet
723 * file indicated by hf if, indeed, it is determined
724 * to be a cabinet.
726 * RETURNS
727 * TRUE if the file is a cabinet. The info pointed to by pfdici will
728 * be provided.
729 * FALSE if the file is not a cabinet, or if an error was encountered
730 * while processing the cabinet. The PERF structure provided to
731 * FDICreate can be queried for more error information.
733 * INCLUDES
734 * fdi.c
736 BOOL __cdecl FDIIsCabinet(
737 HFDI hfdi,
738 INT_PTR hf,
739 PFDICABINETINFO pfdici)
741 BOOL rv;
743 TRACE("(hfdi == ^%p, hf == ^%ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
745 if (!REALLY_IS_FDI(hfdi)) {
746 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
747 SetLastError(ERROR_INVALID_HANDLE);
748 return FALSE;
751 if (!hf) {
752 ERR("(!hf)!\n");
753 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
754 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
755 PFDI_INT(hfdi)->perf->fError = TRUE; */
756 SetLastError(ERROR_INVALID_HANDLE);
757 return FALSE;
760 if (!pfdici) {
761 ERR("(!pfdici)!\n");
762 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
763 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
764 PFDI_INT(hfdi)->perf->fError = TRUE; */
765 SetLastError(ERROR_BAD_ARGUMENTS);
766 return FALSE;
768 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
770 if (rv)
771 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
773 return rv;
776 /******************************************************************
777 * QTMfdi_initmodel (internal)
779 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
781 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
782 int i;
783 m->shiftsleft = 4;
784 m->entries = n;
785 m->syms = sym;
786 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
787 for (i = 0; i < n; i++) {
788 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
789 m->syms[i].sym = i+s; /* actual symbol */
790 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
792 m->syms[n].cumfreq = 0;
795 /******************************************************************
796 * QTMfdi_init (internal)
798 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
799 unsigned int wndsize = 1 << window;
800 int msz = window * 2, i;
801 cab_ULONG j;
803 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
804 /* if a previously allocated window is big enough, keep it */
805 if (window < 10 || window > 21) return DECR_DATAFORMAT;
806 if (QTM(actual_size) < wndsize) {
807 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
808 QTM(window) = NULL;
810 if (!QTM(window)) {
811 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
812 QTM(actual_size) = wndsize;
814 QTM(window_size) = wndsize;
815 QTM(window_posn) = 0;
817 /* initialize static slot/extrabits tables */
818 for (i = 0, j = 0; i < 27; i++) {
819 CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
820 CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
822 for (i = 0, j = 0; i < 42; i++) {
823 CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
824 CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
827 /* initialize arithmetic coding models */
829 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
831 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
832 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
833 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
834 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
836 /* model 4 depends on table size, ranges from 20 to 24 */
837 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
838 /* model 5 depends on table size, ranges from 20 to 36 */
839 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
840 /* model 6pos depends on table size, ranges from 20 to 42 */
841 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
842 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
844 return DECR_OK;
847 /************************************************************
848 * LZXfdi_init (internal)
850 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
851 static const cab_UBYTE bits[] =
852 { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
853 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
854 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
855 17, 17, 17};
856 static const cab_ULONG base[] =
857 { 0, 1, 2, 3, 4, 6, 8, 12,
858 16, 24, 32, 48, 64, 96, 128, 192,
859 256, 384, 512, 768, 1024, 1536, 2048, 3072,
860 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
861 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
862 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
863 1835008, 1966080, 2097152};
864 cab_ULONG wndsize = 1 << window;
865 int posn_slots;
867 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
868 /* if a previously allocated window is big enough, keep it */
869 if (window < 15 || window > 21) return DECR_DATAFORMAT;
870 if (LZX(actual_size) < wndsize) {
871 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
872 LZX(window) = NULL;
874 if (!LZX(window)) {
875 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
876 LZX(actual_size) = wndsize;
878 LZX(window_size) = wndsize;
880 /* initialize static tables */
881 memcpy(CAB(extra_bits), bits, sizeof(bits));
882 memcpy(CAB(lzx_position_base), base, sizeof(base));
884 /* calculate required position slots */
885 if (window == 20) posn_slots = 42;
886 else if (window == 21) posn_slots = 50;
887 else posn_slots = window << 1;
889 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
891 LZX(R0) = LZX(R1) = LZX(R2) = 1;
892 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
893 LZX(header_read) = 0;
894 LZX(frames_read) = 0;
895 LZX(block_remaining) = 0;
896 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
897 LZX(intel_curpos) = 0;
898 LZX(intel_started) = 0;
899 LZX(window_posn) = 0;
901 /* initialize tables to 0 (because deltas will be applied to them) */
902 memset(LZX(MAINTREE_len), 0, sizeof(LZX(MAINTREE_len)));
903 memset(LZX(LENGTH_len), 0, sizeof(LZX(LENGTH_len)));
905 return DECR_OK;
908 /****************************************************
909 * NONEfdi_decomp(internal)
911 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
913 if (inlen != outlen) return DECR_ILLEGALDATA;
914 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
915 return DECR_OK;
918 /********************************************************
919 * Ziphuft_free (internal)
921 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
923 register struct Ziphuft *p, *q;
925 /* Go through linked list, freeing from the allocated (t[-1]) address. */
926 p = t;
927 while (p != (struct Ziphuft *)NULL)
929 q = (--p)->v.t;
930 PFDI_FREE(hfdi, p);
931 p = q;
935 /*********************************************************
936 * fdi_Ziphuft_build (internal)
938 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, const cab_UWORD *d, const cab_UWORD *e,
939 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
941 cab_ULONG a; /* counter for codes of length k */
942 cab_ULONG el; /* length of EOB code (value 256) */
943 cab_ULONG f; /* i repeats in table every f entries */
944 cab_LONG g; /* maximum code length */
945 cab_LONG h; /* table level */
946 register cab_ULONG i; /* counter, current code */
947 register cab_ULONG j; /* counter */
948 register cab_LONG k; /* number of bits in current code */
949 cab_LONG *l; /* stack of bits per table */
950 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
951 register struct Ziphuft *q; /* points to current table */
952 struct Ziphuft r; /* table entry for structure assignment */
953 register cab_LONG w; /* bits before this table == (l * h) */
954 cab_ULONG *xp; /* pointer into x */
955 cab_LONG y; /* number of dummy codes added */
956 cab_ULONG z; /* number of entries in current table */
958 l = ZIP(lx)+1;
960 /* Generate counts for each bit length */
961 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
963 for(i = 0; i < ZIPBMAX+1; ++i)
964 ZIP(c)[i] = 0;
965 p = b; i = n;
968 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
969 } while (--i);
970 if (ZIP(c)[0] == n) /* null input--all zero length codes */
972 *t = (struct Ziphuft *)NULL;
973 *m = 0;
974 return 0;
977 /* Find minimum and maximum length, bound *m by those */
978 for (j = 1; j <= ZIPBMAX; j++)
979 if (ZIP(c)[j])
980 break;
981 k = j; /* minimum code length */
982 if ((cab_ULONG)*m < j)
983 *m = j;
984 for (i = ZIPBMAX; i; i--)
985 if (ZIP(c)[i])
986 break;
987 g = i; /* maximum code length */
988 if ((cab_ULONG)*m > i)
989 *m = i;
991 /* Adjust last length count to fill out codes, if needed */
992 for (y = 1 << j; j < i; j++, y <<= 1)
993 if ((y -= ZIP(c)[j]) < 0)
994 return 2; /* bad input: more codes than bits */
995 if ((y -= ZIP(c)[i]) < 0)
996 return 2;
997 ZIP(c)[i] += y;
999 /* Generate starting offsets LONGo the value table for each length */
1000 ZIP(x)[1] = j = 0;
1001 p = ZIP(c) + 1; xp = ZIP(x) + 2;
1002 while (--i)
1003 { /* note that i == g from above */
1004 *xp++ = (j += *p++);
1007 /* Make a table of values in order of bit lengths */
1008 p = b; i = 0;
1010 if ((j = *p++) != 0)
1011 ZIP(v)[ZIP(x)[j]++] = i;
1012 } while (++i < n);
1015 /* Generate the Huffman codes and for each, make the table entries */
1016 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
1017 p = ZIP(v); /* grab values in bit order */
1018 h = -1; /* no tables yet--level -1 */
1019 w = l[-1] = 0; /* no bits decoded yet */
1020 ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */
1021 q = (struct Ziphuft *)NULL; /* ditto */
1022 z = 0; /* ditto */
1024 /* go through the bit lengths (k already is bits in shortest code) */
1025 for (; k <= g; k++)
1027 a = ZIP(c)[k];
1028 while (a--)
1030 /* here i is the Huffman code of length k bits for value *p */
1031 /* make tables up to required level */
1032 while (k > w + l[h])
1034 w += l[h++]; /* add bits already decoded */
1036 /* compute minimum size table less than or equal to *m bits */
1037 if ((z = g - w) > (cab_ULONG)*m) /* upper limit */
1038 z = *m;
1039 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
1040 { /* too few codes for k-w bit table */
1041 f -= a + 1; /* deduct codes from patterns left */
1042 xp = ZIP(c) + k;
1043 while (++j < z) /* try smaller tables up to z bits */
1045 if ((f <<= 1) <= *++xp)
1046 break; /* enough codes to use up j bits */
1047 f -= *xp; /* else deduct codes from patterns */
1050 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
1051 j = el - w; /* make EOB code end at table */
1052 z = 1 << j; /* table entries for j-bit table */
1053 l[h] = j; /* set table size in stack */
1055 /* allocate and link in new table */
1056 if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
1058 if(h)
1059 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
1060 return 3; /* not enough memory */
1062 *t = q + 1; /* link to list for Ziphuft_free() */
1063 *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
1064 ZIP(u)[h] = ++q; /* table starts after link */
1066 /* connect to last table, if there is one */
1067 if (h)
1069 ZIP(x)[h] = i; /* save pattern for backing up */
1070 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
1071 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
1072 r.v.t = q; /* pointer to this table */
1073 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
1074 ZIP(u)[h-1][j] = r; /* connect to last table */
1078 /* set up table entry in r */
1079 r.b = (cab_UBYTE)(k - w);
1080 if (p >= ZIP(v) + n)
1081 r.e = 99; /* out of values--invalid code */
1082 else if (*p < s)
1084 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
1085 r.v.n = *p++; /* simple code is just the value */
1087 else
1089 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
1090 r.v.n = d[*p++ - s];
1093 /* fill code-like entries with r */
1094 f = 1 << (k - w);
1095 for (j = i >> w; j < z; j += f)
1096 q[j] = r;
1098 /* backwards increment the k-bit code i */
1099 for (j = 1 << (k - 1); i & j; j >>= 1)
1100 i ^= j;
1101 i ^= j;
1103 /* backup over finished tables */
1104 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
1105 w -= l[--h]; /* don't need to update q */
1109 /* return actual size of base table */
1110 *m = l[0];
1112 /* Return true (1) if we were given an incomplete table */
1113 return y != 0 && g != 1;
1116 /*********************************************************
1117 * fdi_Zipinflate_codes (internal)
1119 static cab_LONG fdi_Zipinflate_codes(const struct Ziphuft *tl, const struct Ziphuft *td,
1120 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
1122 register cab_ULONG e; /* table entry flag/number of extra bits */
1123 cab_ULONG n, d; /* length and index for copy */
1124 cab_ULONG w; /* current window position */
1125 const struct Ziphuft *t; /* pointer to table entry */
1126 cab_ULONG ml, md; /* masks for bl and bd bits */
1127 register cab_ULONG b; /* bit buffer */
1128 register cab_ULONG k; /* number of bits in bit buffer */
1130 /* make local copies of globals */
1131 b = ZIP(bb); /* initialize bit buffer */
1132 k = ZIP(bk);
1133 w = ZIP(window_posn); /* initialize window position */
1135 /* inflate the coded data */
1136 ml = Zipmask[bl]; /* precompute masks for speed */
1137 md = Zipmask[bd];
1139 for(;;)
1141 ZIPNEEDBITS((cab_ULONG)bl)
1142 if((e = (t = tl + (b & ml))->e) > 16)
1145 if (e == 99)
1146 return 1;
1147 ZIPDUMPBITS(t->b)
1148 e -= 16;
1149 ZIPNEEDBITS(e)
1150 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1151 ZIPDUMPBITS(t->b)
1152 if (e == 16) /* then it's a literal */
1153 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
1154 else /* it's an EOB or a length */
1156 /* exit if end of block */
1157 if(e == 15)
1158 break;
1160 /* get length of block to copy */
1161 ZIPNEEDBITS(e)
1162 n = t->v.n + (b & Zipmask[e]);
1163 ZIPDUMPBITS(e);
1165 /* decode distance of block to copy */
1166 ZIPNEEDBITS((cab_ULONG)bd)
1167 if ((e = (t = td + (b & md))->e) > 16)
1168 do {
1169 if (e == 99)
1170 return 1;
1171 ZIPDUMPBITS(t->b)
1172 e -= 16;
1173 ZIPNEEDBITS(e)
1174 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1175 ZIPDUMPBITS(t->b)
1176 ZIPNEEDBITS(e)
1177 d = w - t->v.n - (b & Zipmask[e]);
1178 ZIPDUMPBITS(e)
1181 d &= ZIPWSIZE - 1;
1182 e = ZIPWSIZE - max(d, w);
1183 e = min(e, n);
1184 n -= e;
1187 CAB(outbuf)[w++] = CAB(outbuf)[d++];
1188 } while (--e);
1189 } while (n);
1193 /* restore the globals from the locals */
1194 ZIP(window_posn) = w; /* restore global window pointer */
1195 ZIP(bb) = b; /* restore global bit buffer */
1196 ZIP(bk) = k;
1198 /* done */
1199 return 0;
1202 /***********************************************************
1203 * Zipinflate_stored (internal)
1205 static cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1206 /* "decompress" an inflated type 0 (stored) block. */
1208 cab_ULONG n; /* number of bytes in block */
1209 cab_ULONG w; /* current window position */
1210 register cab_ULONG b; /* bit buffer */
1211 register cab_ULONG k; /* number of bits in bit buffer */
1213 /* make local copies of globals */
1214 b = ZIP(bb); /* initialize bit buffer */
1215 k = ZIP(bk);
1216 w = ZIP(window_posn); /* initialize window position */
1218 /* go to byte boundary */
1219 n = k & 7;
1220 ZIPDUMPBITS(n);
1222 /* get the length and its complement */
1223 ZIPNEEDBITS(16)
1224 n = (b & 0xffff);
1225 ZIPDUMPBITS(16)
1226 ZIPNEEDBITS(16)
1227 if (n != ((~b) & 0xffff))
1228 return 1; /* error in compressed data */
1229 ZIPDUMPBITS(16)
1231 /* read and output the compressed data */
1232 while(n--)
1234 ZIPNEEDBITS(8)
1235 CAB(outbuf)[w++] = (cab_UBYTE)b;
1236 ZIPDUMPBITS(8)
1239 /* restore the globals from the locals */
1240 ZIP(window_posn) = w; /* restore global window pointer */
1241 ZIP(bb) = b; /* restore global bit buffer */
1242 ZIP(bk) = k;
1243 return 0;
1246 /******************************************************
1247 * fdi_Zipinflate_fixed (internal)
1249 static cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1251 struct Ziphuft *fixed_tl;
1252 struct Ziphuft *fixed_td;
1253 cab_LONG fixed_bl, fixed_bd;
1254 cab_LONG i; /* temporary variable */
1255 cab_ULONG *l;
1257 l = ZIP(ll);
1259 /* literal table */
1260 for(i = 0; i < 144; i++)
1261 l[i] = 8;
1262 for(; i < 256; i++)
1263 l[i] = 9;
1264 for(; i < 280; i++)
1265 l[i] = 7;
1266 for(; i < 288; i++) /* make a complete, but wrong code set */
1267 l[i] = 8;
1268 fixed_bl = 7;
1269 if((i = fdi_Ziphuft_build(l, 288, 257, Zipcplens, Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1270 return i;
1272 /* distance table */
1273 for(i = 0; i < 30; i++) /* make an incomplete code set */
1274 l[i] = 5;
1275 fixed_bd = 5;
1276 if((i = fdi_Ziphuft_build(l, 30, 0, Zipcpdist, Zipcpdext, &fixed_td, &fixed_bd, decomp_state)) > 1)
1278 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1279 return i;
1282 /* decompress until an end-of-block code */
1283 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1285 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1286 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1287 return i;
1290 /**************************************************************
1291 * fdi_Zipinflate_dynamic (internal)
1293 static cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1294 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1296 cab_LONG i; /* temporary variables */
1297 cab_ULONG j;
1298 cab_ULONG *ll;
1299 cab_ULONG l; /* last length */
1300 cab_ULONG m; /* mask for bit lengths table */
1301 cab_ULONG n; /* number of lengths to get */
1302 struct Ziphuft *tl; /* literal/length code table */
1303 struct Ziphuft *td; /* distance code table */
1304 cab_LONG bl; /* lookup bits for tl */
1305 cab_LONG bd; /* lookup bits for td */
1306 cab_ULONG nb; /* number of bit length codes */
1307 cab_ULONG nl; /* number of literal/length codes */
1308 cab_ULONG nd; /* number of distance codes */
1309 register cab_ULONG b; /* bit buffer */
1310 register cab_ULONG k; /* number of bits in bit buffer */
1312 /* make local bit buffer */
1313 b = ZIP(bb);
1314 k = ZIP(bk);
1315 ll = ZIP(ll);
1317 /* read in table lengths */
1318 ZIPNEEDBITS(5)
1319 nl = 257 + (b & 0x1f); /* number of literal/length codes */
1320 ZIPDUMPBITS(5)
1321 ZIPNEEDBITS(5)
1322 nd = 1 + (b & 0x1f); /* number of distance codes */
1323 ZIPDUMPBITS(5)
1324 ZIPNEEDBITS(4)
1325 nb = 4 + (b & 0xf); /* number of bit length codes */
1326 ZIPDUMPBITS(4)
1327 if(nl > 288 || nd > 32)
1328 return 1; /* bad lengths */
1330 /* read in bit-length-code lengths */
1331 for(j = 0; j < nb; j++)
1333 ZIPNEEDBITS(3)
1334 ll[Zipborder[j]] = b & 7;
1335 ZIPDUMPBITS(3)
1337 for(; j < 19; j++)
1338 ll[Zipborder[j]] = 0;
1340 /* build decoding table for trees--single level, 7 bit lookup */
1341 bl = 7;
1342 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1344 if(i == 1)
1345 fdi_Ziphuft_free(CAB(hfdi), tl);
1346 return i; /* incomplete code set */
1349 /* read in literal and distance code lengths */
1350 n = nl + nd;
1351 m = Zipmask[bl];
1352 i = l = 0;
1353 while((cab_ULONG)i < n)
1355 ZIPNEEDBITS((cab_ULONG)bl)
1356 j = (td = tl + (b & m))->b;
1357 ZIPDUMPBITS(j)
1358 j = td->v.n;
1359 if (j < 16) /* length of code in bits (0..15) */
1360 ll[i++] = l = j; /* save last length in l */
1361 else if (j == 16) /* repeat last length 3 to 6 times */
1363 ZIPNEEDBITS(2)
1364 j = 3 + (b & 3);
1365 ZIPDUMPBITS(2)
1366 if((cab_ULONG)i + j > n)
1367 return 1;
1368 while (j--)
1369 ll[i++] = l;
1371 else if (j == 17) /* 3 to 10 zero length codes */
1373 ZIPNEEDBITS(3)
1374 j = 3 + (b & 7);
1375 ZIPDUMPBITS(3)
1376 if ((cab_ULONG)i + j > n)
1377 return 1;
1378 while (j--)
1379 ll[i++] = 0;
1380 l = 0;
1382 else /* j == 18: 11 to 138 zero length codes */
1384 ZIPNEEDBITS(7)
1385 j = 11 + (b & 0x7f);
1386 ZIPDUMPBITS(7)
1387 if ((cab_ULONG)i + j > n)
1388 return 1;
1389 while (j--)
1390 ll[i++] = 0;
1391 l = 0;
1395 /* free decoding table for trees */
1396 fdi_Ziphuft_free(CAB(hfdi), tl);
1398 /* restore the global bit buffer */
1399 ZIP(bb) = b;
1400 ZIP(bk) = k;
1402 /* build the decoding tables for literal/length and distance codes */
1403 bl = ZIPLBITS;
1404 if((i = fdi_Ziphuft_build(ll, nl, 257, Zipcplens, Zipcplext, &tl, &bl, decomp_state)) != 0)
1406 if(i == 1)
1407 fdi_Ziphuft_free(CAB(hfdi), tl);
1408 return i; /* incomplete code set */
1410 bd = ZIPDBITS;
1411 fdi_Ziphuft_build(ll + nl, nd, 0, Zipcpdist, Zipcpdext, &td, &bd, decomp_state);
1413 /* decompress until an end-of-block code */
1414 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1415 return 1;
1417 /* free the decoding tables, return */
1418 fdi_Ziphuft_free(CAB(hfdi), tl);
1419 fdi_Ziphuft_free(CAB(hfdi), td);
1420 return 0;
1423 /*****************************************************
1424 * fdi_Zipinflate_block (internal)
1426 static cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1427 { /* decompress an inflated block */
1428 cab_ULONG t; /* block type */
1429 register cab_ULONG b; /* bit buffer */
1430 register cab_ULONG k; /* number of bits in bit buffer */
1432 /* make local bit buffer */
1433 b = ZIP(bb);
1434 k = ZIP(bk);
1436 /* read in last block bit */
1437 ZIPNEEDBITS(1)
1438 *e = (cab_LONG)b & 1;
1439 ZIPDUMPBITS(1)
1441 /* read in block type */
1442 ZIPNEEDBITS(2)
1443 t = b & 3;
1444 ZIPDUMPBITS(2)
1446 /* restore the global bit buffer */
1447 ZIP(bb) = b;
1448 ZIP(bk) = k;
1450 /* inflate that block type */
1451 if(t == 2)
1452 return fdi_Zipinflate_dynamic(decomp_state);
1453 if(t == 0)
1454 return fdi_Zipinflate_stored(decomp_state);
1455 if(t == 1)
1456 return fdi_Zipinflate_fixed(decomp_state);
1457 /* bad block type */
1458 return 2;
1461 /****************************************************
1462 * ZIPfdi_decomp(internal)
1464 static int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1466 cab_LONG e; /* last block flag */
1468 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1470 ZIP(inpos) = CAB(inbuf);
1471 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1472 if(outlen > ZIPWSIZE)
1473 return DECR_DATAFORMAT;
1475 /* CK = Chris Kirmse, official Microsoft purloiner */
1476 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1477 return DECR_ILLEGALDATA;
1478 ZIP(inpos) += 2;
1480 do {
1481 if(fdi_Zipinflate_block(&e, decomp_state))
1482 return DECR_ILLEGALDATA;
1483 } while(!e);
1485 /* return success */
1486 return DECR_OK;
1489 /*******************************************************************
1490 * QTMfdi_decomp(internal)
1492 static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1494 cab_UBYTE *inpos = CAB(inbuf);
1495 cab_UBYTE *window = QTM(window);
1496 cab_UBYTE *runsrc, *rundest;
1497 cab_ULONG window_posn = QTM(window_posn);
1498 cab_ULONG window_size = QTM(window_size);
1500 /* used by bitstream macros */
1501 register int bitsleft, bitrun, bitsneed;
1502 register cab_ULONG bitbuf;
1504 /* used by GET_SYMBOL */
1505 cab_ULONG range;
1506 cab_UWORD symf;
1507 int i;
1509 int extra, togo = outlen, match_length = 0, copy_length;
1510 cab_UBYTE selector, sym;
1511 cab_ULONG match_offset = 0;
1513 cab_UWORD H = 0xFFFF, L = 0, C;
1515 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1517 /* read initial value of C */
1518 Q_INIT_BITSTREAM;
1519 Q_READ_BITS(C, 16);
1521 /* apply 2^x-1 mask */
1522 window_posn &= window_size - 1;
1523 /* runs can't straddle the window wraparound */
1524 if ((window_posn + togo) > window_size) {
1525 TRACE("straddled run\n");
1526 return DECR_DATAFORMAT;
1529 while (togo > 0) {
1530 GET_SYMBOL(model7, selector);
1531 switch (selector) {
1532 case 0:
1533 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1534 break;
1535 case 1:
1536 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1537 break;
1538 case 2:
1539 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1540 break;
1541 case 3:
1542 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1543 break;
1545 case 4:
1546 /* selector 4 = fixed length of 3 */
1547 GET_SYMBOL(model4, sym);
1548 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1549 match_offset = CAB(q_position_base)[sym] + extra + 1;
1550 match_length = 3;
1551 break;
1553 case 5:
1554 /* selector 5 = fixed length of 4 */
1555 GET_SYMBOL(model5, sym);
1556 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1557 match_offset = CAB(q_position_base)[sym] + extra + 1;
1558 match_length = 4;
1559 break;
1561 case 6:
1562 /* selector 6 = variable length */
1563 GET_SYMBOL(model6len, sym);
1564 Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1565 match_length = CAB(q_length_base)[sym] + extra + 5;
1566 GET_SYMBOL(model6pos, sym);
1567 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1568 match_offset = CAB(q_position_base)[sym] + extra + 1;
1569 break;
1571 default:
1572 TRACE("Selector is bogus\n");
1573 return DECR_ILLEGALDATA;
1576 /* if this is a match */
1577 if (selector >= 4) {
1578 rundest = window + window_posn;
1579 togo -= match_length;
1581 /* copy any wrapped around source data */
1582 if (window_posn >= match_offset) {
1583 /* no wrap */
1584 runsrc = rundest - match_offset;
1585 } else {
1586 runsrc = rundest + (window_size - match_offset);
1587 copy_length = match_offset - window_posn;
1588 if (copy_length < match_length) {
1589 match_length -= copy_length;
1590 window_posn += copy_length;
1591 while (copy_length-- > 0) *rundest++ = *runsrc++;
1592 runsrc = window;
1595 window_posn += match_length;
1597 /* copy match data - no worries about destination wraps */
1598 while (match_length-- > 0) *rundest++ = *runsrc++;
1600 } /* while (togo > 0) */
1602 if (togo != 0) {
1603 TRACE("Frame overflow, this_run = %d\n", togo);
1604 return DECR_ILLEGALDATA;
1607 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1608 outlen, outlen);
1610 QTM(window_posn) = window_posn;
1611 return DECR_OK;
1614 /************************************************************
1615 * fdi_lzx_read_lens (internal)
1617 static int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1618 fdi_decomp_state *decomp_state) {
1619 cab_ULONG i,j, x,y;
1620 int z;
1622 register cab_ULONG bitbuf = lb->bb;
1623 register int bitsleft = lb->bl;
1624 cab_UBYTE *inpos = lb->ip;
1625 cab_UWORD *hufftbl;
1627 for (x = 0; x < 20; x++) {
1628 READ_BITS(y, 4);
1629 LENTABLE(PRETREE)[x] = y;
1631 BUILD_TABLE(PRETREE);
1633 for (x = first; x < last; ) {
1634 READ_HUFFSYM(PRETREE, z);
1635 if (z == 17) {
1636 READ_BITS(y, 4); y += 4;
1637 while (y--) lens[x++] = 0;
1639 else if (z == 18) {
1640 READ_BITS(y, 5); y += 20;
1641 while (y--) lens[x++] = 0;
1643 else if (z == 19) {
1644 READ_BITS(y, 1); y += 4;
1645 READ_HUFFSYM(PRETREE, z);
1646 z = lens[x] - z; if (z < 0) z += 17;
1647 while (y--) lens[x++] = z;
1649 else {
1650 z = lens[x] - z; if (z < 0) z += 17;
1651 lens[x++] = z;
1655 lb->bb = bitbuf;
1656 lb->bl = bitsleft;
1657 lb->ip = inpos;
1658 return 0;
1661 /*******************************************************
1662 * LZXfdi_decomp(internal)
1664 static int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1665 cab_UBYTE *inpos = CAB(inbuf);
1666 const cab_UBYTE *endinp = inpos + inlen;
1667 cab_UBYTE *window = LZX(window);
1668 cab_UBYTE *runsrc, *rundest;
1669 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1671 cab_ULONG window_posn = LZX(window_posn);
1672 cab_ULONG window_size = LZX(window_size);
1673 cab_ULONG R0 = LZX(R0);
1674 cab_ULONG R1 = LZX(R1);
1675 cab_ULONG R2 = LZX(R2);
1677 register cab_ULONG bitbuf;
1678 register int bitsleft;
1679 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1680 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1682 int togo = outlen, this_run, main_element, aligned_bits;
1683 int match_length, copy_length, length_footer, extra, verbatim_bits;
1685 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1687 INIT_BITSTREAM;
1689 /* read header if necessary */
1690 if (!LZX(header_read)) {
1691 i = j = 0;
1692 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1693 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1694 LZX(header_read) = 1;
1697 /* main decoding loop */
1698 while (togo > 0) {
1699 /* last block finished, new block expected */
1700 if (LZX(block_remaining) == 0) {
1701 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1702 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1703 INIT_BITSTREAM;
1706 READ_BITS(LZX(block_type), 3);
1707 READ_BITS(i, 16);
1708 READ_BITS(j, 8);
1709 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1711 switch (LZX(block_type)) {
1712 case LZX_BLOCKTYPE_ALIGNED:
1713 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1714 BUILD_TABLE(ALIGNED);
1715 /* rest of aligned header is same as verbatim */
1717 case LZX_BLOCKTYPE_VERBATIM:
1718 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1719 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1720 BUILD_TABLE(MAINTREE);
1721 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1723 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1724 BUILD_TABLE(LENGTH);
1725 break;
1727 case LZX_BLOCKTYPE_UNCOMPRESSED:
1728 LZX(intel_started) = 1; /* because we can't assume otherwise */
1729 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1730 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1731 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1732 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1733 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1734 break;
1736 default:
1737 return DECR_ILLEGALDATA;
1741 /* buffer exhaustion check */
1742 if (inpos > endinp) {
1743 /* it's possible to have a file where the next run is less than
1744 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1745 * in building the tables will exhaust the buffer, so we should
1746 * allow for this, but not allow those accidentally read bits to
1747 * be used (so we check that there are at least 16 bits
1748 * remaining - in this boundary case they aren't really part of
1749 * the compressed data)
1751 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1754 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1755 if (this_run > togo) this_run = togo;
1756 togo -= this_run;
1757 LZX(block_remaining) -= this_run;
1759 /* apply 2^x-1 mask */
1760 window_posn &= window_size - 1;
1761 /* runs can't straddle the window wraparound */
1762 if ((window_posn + this_run) > window_size)
1763 return DECR_DATAFORMAT;
1765 switch (LZX(block_type)) {
1767 case LZX_BLOCKTYPE_VERBATIM:
1768 while (this_run > 0) {
1769 READ_HUFFSYM(MAINTREE, main_element);
1771 if (main_element < LZX_NUM_CHARS) {
1772 /* literal: 0 to LZX_NUM_CHARS-1 */
1773 window[window_posn++] = main_element;
1774 this_run--;
1776 else {
1777 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1778 main_element -= LZX_NUM_CHARS;
1780 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1781 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1782 READ_HUFFSYM(LENGTH, length_footer);
1783 match_length += length_footer;
1785 match_length += LZX_MIN_MATCH;
1787 match_offset = main_element >> 3;
1789 if (match_offset > 2) {
1790 /* not repeated offset */
1791 if (match_offset != 3) {
1792 extra = CAB(extra_bits)[match_offset];
1793 READ_BITS(verbatim_bits, extra);
1794 match_offset = CAB(lzx_position_base)[match_offset]
1795 - 2 + verbatim_bits;
1797 else {
1798 match_offset = 1;
1801 /* update repeated offset LRU queue */
1802 R2 = R1; R1 = R0; R0 = match_offset;
1804 else if (match_offset == 0) {
1805 match_offset = R0;
1807 else if (match_offset == 1) {
1808 match_offset = R1;
1809 R1 = R0; R0 = match_offset;
1811 else /* match_offset == 2 */ {
1812 match_offset = R2;
1813 R2 = R0; R0 = match_offset;
1816 rundest = window + window_posn;
1817 this_run -= match_length;
1819 /* copy any wrapped around source data */
1820 if (window_posn >= match_offset) {
1821 /* no wrap */
1822 runsrc = rundest - match_offset;
1823 } else {
1824 runsrc = rundest + (window_size - match_offset);
1825 copy_length = match_offset - window_posn;
1826 if (copy_length < match_length) {
1827 match_length -= copy_length;
1828 window_posn += copy_length;
1829 while (copy_length-- > 0) *rundest++ = *runsrc++;
1830 runsrc = window;
1833 window_posn += match_length;
1835 /* copy match data - no worries about destination wraps */
1836 while (match_length-- > 0) *rundest++ = *runsrc++;
1839 break;
1841 case LZX_BLOCKTYPE_ALIGNED:
1842 while (this_run > 0) {
1843 READ_HUFFSYM(MAINTREE, main_element);
1845 if (main_element < LZX_NUM_CHARS) {
1846 /* literal: 0 to LZX_NUM_CHARS-1 */
1847 window[window_posn++] = main_element;
1848 this_run--;
1850 else {
1851 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1852 main_element -= LZX_NUM_CHARS;
1854 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1855 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1856 READ_HUFFSYM(LENGTH, length_footer);
1857 match_length += length_footer;
1859 match_length += LZX_MIN_MATCH;
1861 match_offset = main_element >> 3;
1863 if (match_offset > 2) {
1864 /* not repeated offset */
1865 extra = CAB(extra_bits)[match_offset];
1866 match_offset = CAB(lzx_position_base)[match_offset] - 2;
1867 if (extra > 3) {
1868 /* verbatim and aligned bits */
1869 extra -= 3;
1870 READ_BITS(verbatim_bits, extra);
1871 match_offset += (verbatim_bits << 3);
1872 READ_HUFFSYM(ALIGNED, aligned_bits);
1873 match_offset += aligned_bits;
1875 else if (extra == 3) {
1876 /* aligned bits only */
1877 READ_HUFFSYM(ALIGNED, aligned_bits);
1878 match_offset += aligned_bits;
1880 else if (extra > 0) { /* extra==1, extra==2 */
1881 /* verbatim bits only */
1882 READ_BITS(verbatim_bits, extra);
1883 match_offset += verbatim_bits;
1885 else /* extra == 0 */ {
1886 /* ??? */
1887 match_offset = 1;
1890 /* update repeated offset LRU queue */
1891 R2 = R1; R1 = R0; R0 = match_offset;
1893 else if (match_offset == 0) {
1894 match_offset = R0;
1896 else if (match_offset == 1) {
1897 match_offset = R1;
1898 R1 = R0; R0 = match_offset;
1900 else /* match_offset == 2 */ {
1901 match_offset = R2;
1902 R2 = R0; R0 = match_offset;
1905 rundest = window + window_posn;
1906 this_run -= match_length;
1908 /* copy any wrapped around source data */
1909 if (window_posn >= match_offset) {
1910 /* no wrap */
1911 runsrc = rundest - match_offset;
1912 } else {
1913 runsrc = rundest + (window_size - match_offset);
1914 copy_length = match_offset - window_posn;
1915 if (copy_length < match_length) {
1916 match_length -= copy_length;
1917 window_posn += copy_length;
1918 while (copy_length-- > 0) *rundest++ = *runsrc++;
1919 runsrc = window;
1922 window_posn += match_length;
1924 /* copy match data - no worries about destination wraps */
1925 while (match_length-- > 0) *rundest++ = *runsrc++;
1928 break;
1930 case LZX_BLOCKTYPE_UNCOMPRESSED:
1931 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1932 memcpy(window + window_posn, inpos, (size_t) this_run);
1933 inpos += this_run; window_posn += this_run;
1934 break;
1936 default:
1937 return DECR_ILLEGALDATA; /* might as well */
1943 if (togo != 0) return DECR_ILLEGALDATA;
1944 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1945 outlen, (size_t) outlen);
1947 LZX(window_posn) = window_posn;
1948 LZX(R0) = R0;
1949 LZX(R1) = R1;
1950 LZX(R2) = R2;
1952 /* intel E8 decoding */
1953 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1954 if (outlen <= 6 || !LZX(intel_started)) {
1955 LZX(intel_curpos) += outlen;
1957 else {
1958 cab_UBYTE *data = CAB(outbuf);
1959 cab_UBYTE *dataend = data + outlen - 10;
1960 cab_LONG curpos = LZX(intel_curpos);
1961 cab_LONG filesize = LZX(intel_filesize);
1962 cab_LONG abs_off, rel_off;
1964 LZX(intel_curpos) = curpos + outlen;
1966 while (data < dataend) {
1967 if (*data++ != 0xE8) { curpos++; continue; }
1968 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1969 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1970 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1971 data[0] = (cab_UBYTE) rel_off;
1972 data[1] = (cab_UBYTE) (rel_off >> 8);
1973 data[2] = (cab_UBYTE) (rel_off >> 16);
1974 data[3] = (cab_UBYTE) (rel_off >> 24);
1976 data += 4;
1977 curpos += 5;
1981 return DECR_OK;
1984 /**********************************************************
1985 * fdi_decomp (internal)
1987 * Decompress the requested number of bytes. If savemode is zero,
1988 * do not save the output anywhere, just plow through blocks until we
1989 * reach the specified (uncompressed) distance from the starting point,
1990 * and remember the position of the cabfile pointer (and which cabfile)
1991 * after we are done; otherwise, save the data out to CAB(filehf),
1992 * decompressing the requested number of bytes and writing them out. This
1993 * is also where we jump to additional cabinets in the case of split
1994 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1996 static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
1997 char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
1999 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
2000 cab_UBYTE buf[cfdata_SIZEOF], *data;
2001 cab_UWORD inlen, len, outlen, cando;
2002 cab_ULONG cksum;
2003 cab_LONG err;
2004 fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
2006 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
2008 while (bytes > 0) {
2009 /* cando = the max number of bytes we can do */
2010 cando = CAB(outlen);
2011 if (cando > bytes) cando = bytes;
2013 /* if cando != 0 */
2014 if (cando && savemode)
2015 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
2017 CAB(outpos) += cando;
2018 CAB(outlen) -= cando;
2019 bytes -= cando; if (!bytes) break;
2021 /* we only get here if we emptied the output buffer */
2023 /* read data header + data */
2024 inlen = outlen = 0;
2025 while (outlen == 0) {
2026 /* read the block header, skip the reserved part */
2027 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
2028 return DECR_INPUT;
2030 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
2031 return DECR_INPUT;
2033 /* we shouldn't get blocks over CAB_INPUTMAX in size */
2034 data = CAB(inbuf) + inlen;
2035 len = EndGetI16(buf+cfdata_CompressedSize);
2036 inlen += len;
2037 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
2038 if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
2039 return DECR_INPUT;
2041 /* clear two bytes after read-in data */
2042 data[len+1] = data[len+2] = 0;
2044 /* perform checksum test on the block (if one is stored) */
2045 cksum = EndGetI32(buf+cfdata_CheckSum);
2046 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
2047 return DECR_CHECKSUM; /* checksum is wrong */
2049 outlen = EndGetI16(buf+cfdata_UncompressedSize);
2051 /* outlen=0 means this block was the last contiguous part
2052 of a split block, continued in the next cabinet */
2053 if (outlen == 0) {
2054 int pathlen, filenamelen, idx, i, cabhf;
2055 char fullpath[MAX_PATH], userpath[256];
2056 FDINOTIFICATION fdin;
2057 FDICABINETINFO fdici;
2058 char emptystring = '\0';
2059 cab_UBYTE buf2[64];
2060 int success = FALSE;
2061 struct fdi_folder *fol = NULL, *linkfol = NULL;
2062 struct fdi_file *file = NULL, *linkfile = NULL;
2064 tryanothercab:
2066 /* set up the next decomp_state... */
2067 if (!(cab->next)) {
2068 if (!cab->mii.hasnext) return DECR_INPUT;
2070 if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
2071 return DECR_NOMEMORY;
2073 ZeroMemory(cab->next, sizeof(fdi_decomp_state));
2075 /* copy pszCabPath to userpath */
2076 ZeroMemory(userpath, 256);
2077 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2078 if (pathlen) {
2079 if (pathlen < 256) {
2080 for (i = 0; i <= pathlen; i++)
2081 userpath[i] = pszCabPath[i];
2082 } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2085 /* initial fdintNEXT_CABINET notification */
2086 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2087 fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
2088 fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
2089 fdin.psz3 = &userpath[0];
2090 fdin.fdie = FDIERROR_NONE;
2091 fdin.pv = pvUser;
2093 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2095 do {
2097 pathlen = strlen(userpath);
2098 filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
2100 /* slight overestimation here to save CPU cycles in the developer's brain */
2101 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2102 ERR("MAX_PATH exceeded.\n");
2103 return DECR_ILLEGALDATA;
2106 /* paste the path and filename together */
2107 idx = 0;
2108 if (pathlen) {
2109 for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
2110 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2112 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
2113 fullpath[idx] = '\0';
2115 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2117 /* try to get a handle to the cabfile */
2118 cabhf = PFDI_OPEN(CAB(hfdi), fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2119 if (cabhf == -1) {
2120 /* no file. allow the user to try again */
2121 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2122 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2123 continue;
2126 if (cabhf == 0) {
2127 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2128 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2129 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2130 continue;
2133 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2134 if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
2135 WARN("FDIIsCabinet failed.\n");
2136 PFDI_CLOSE(CAB(hfdi), cabhf);
2137 fdin.fdie = FDIERROR_NOT_A_CABINET;
2138 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2139 continue;
2142 if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
2143 WARN("Wrong Cabinet.\n");
2144 PFDI_CLOSE(CAB(hfdi), cabhf);
2145 fdin.fdie = FDIERROR_WRONG_CABINET;
2146 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2147 continue;
2150 break;
2152 } while (1);
2154 /* cabinet notification */
2155 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2156 fdin.setID = fdici.setID;
2157 fdin.iCabinet = fdici.iCabinet;
2158 fdin.pv = pvUser;
2159 fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2160 fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2161 fdin.psz3 = pszCabPath;
2163 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2165 cab->next->setID = fdici.setID;
2166 cab->next->iCabinet = fdici.iCabinet;
2167 cab->next->hfdi = CAB(hfdi);
2168 cab->next->filehf = CAB(filehf);
2169 cab->next->cabhf = cabhf;
2170 cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2172 cab = cab->next; /* advance to the next cabinet */
2174 /* read folders */
2175 for (i = 0; i < fdici.cFolders; i++) {
2176 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF)
2177 return DECR_INPUT;
2179 if (cab->mii.folder_resv > 0)
2180 PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2182 fol = (struct fdi_folder *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2183 if (!fol) {
2184 ERR("out of memory!\n");
2185 return DECR_NOMEMORY;
2187 ZeroMemory(fol, sizeof(struct fdi_folder));
2188 if (!(cab->firstfol)) cab->firstfol = fol;
2190 fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2191 fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2192 fol->comp_type = EndGetI16(buf2+cffold_CompType);
2194 if (linkfol)
2195 linkfol->next = fol;
2196 linkfol = fol;
2199 /* read files */
2200 for (i = 0; i < fdici.cFiles; i++) {
2201 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2202 return DECR_INPUT;
2204 file = (struct fdi_file *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2205 if (!file) {
2206 ERR("out of memory!\n");
2207 return DECR_NOMEMORY;
2209 ZeroMemory(file, sizeof(struct fdi_file));
2210 if (!(cab->firstfile)) cab->firstfile = file;
2212 file->length = EndGetI32(buf2+cffile_UncompressedSize);
2213 file->offset = EndGetI32(buf2+cffile_FolderOffset);
2214 file->index = EndGetI16(buf2+cffile_FolderIndex);
2215 file->time = EndGetI16(buf2+cffile_Time);
2216 file->date = EndGetI16(buf2+cffile_Date);
2217 file->attribs = EndGetI16(buf2+cffile_Attribs);
2218 file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2220 if (!file->filename) return DECR_INPUT;
2222 if (linkfile)
2223 linkfile->next = file;
2224 linkfile = file;
2227 } else
2228 cab = cab->next; /* advance to the next cabinet */
2230 /* iterate files -- if we encounter the continued file, process it --
2231 otherwise, jump to the label above and keep looking */
2233 for (file = cab->firstfile; (file); file = file->next) {
2234 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2235 /* check to ensure a real match */
2236 if (lstrcmpiA(fi->filename, file->filename) == 0) {
2237 success = TRUE;
2238 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2239 return DECR_INPUT;
2240 break;
2244 if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2245 "Wrong Cabinet" notification? */
2249 /* decompress block */
2250 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2251 return err;
2252 CAB(outlen) = outlen;
2253 CAB(outpos) = CAB(outbuf);
2256 CAB(decomp_cab) = cab;
2257 return DECR_OK;
2260 /***********************************************************************
2261 * FDICopy (CABINET.22)
2263 * Iterates through the files in the Cabinet file indicated by name and
2264 * file-location. May chain forward to additional cabinets (typically
2265 * only one) if files which begin in this Cabinet are continued in another
2266 * cabinet. For each file which is partially contained in this cabinet,
2267 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2268 * notification to the pfnfdin callback. For each file which begins in
2269 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2270 * callback, and the file is optionally decompressed and saved to disk.
2271 * Notification is not provided for files which are not at least partially
2272 * contained in the specified cabinet file.
2274 * See below for a thorough explanation of the various notification
2275 * callbacks.
2277 * PARAMS
2278 * hfdi [I] An HFDI from FDICreate
2279 * pszCabinet [I] C-style string containing the filename of the cabinet
2280 * pszCabPath [I] C-style string containing the file path of the cabinet
2281 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2282 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2283 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2284 * value: NULL.
2285 * pvUser [I] arbitrary void * value which is passed to callbacks.
2287 * RETURNS
2288 * TRUE if successful.
2289 * FALSE if unsuccessful (error information is provided in the ERF structure
2290 * associated with the provided decompression handle by FDICreate).
2292 * CALLBACKS
2294 * Two pointers to callback functions are provided as parameters to FDICopy:
2295 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2296 * types are as follows:
2298 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2299 * PFDINOTIFICATION pfdin );
2301 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2303 * You can create functions of this type using the FNFDINOTIFY() and
2304 * FNFDIDECRYPT() macros, respectively. For example:
2306 * FNFDINOTIFY(mycallback) {
2307 * / * use variables fdint and pfdin to process notification * /
2310 * The second callback, which could be used for decrypting encrypted data,
2311 * is not used at all.
2313 * Each notification informs the user of some event which has occurred during
2314 * decompression of the cabinet file; each notification is also an opportunity
2315 * for the callee to abort decompression. The information provided to the
2316 * callback and the meaning of the callback's return value vary drastically
2317 * across the various types of notification. The type of notification is the
2318 * fdint parameter; all other information is provided to the callback in
2319 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2320 * pfdin. The only part of that structure which is assigned for every callback
2321 * is the pv element, which contains the arbitrary value which was passed to
2322 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2323 * is highly dependent on fdint).
2325 * If you encounter unknown notifications, you should return zero if you want
2326 * decompression to continue (or -1 to abort). All strings used in the
2327 * callbacks are regular C-style strings. Detailed descriptions of each
2328 * notification type follow:
2330 * fdintCABINET_INFO:
2332 * This is the first notification provided after calling FDICopy, and provides
2333 * the user with various information about the cabinet. Note that this is
2334 * called for each cabinet FDICopy opens, not just the first one. In the
2335 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2336 * next cabinet file in the set after the one just loaded (if any), psz2
2337 * contains a pointer to the name or "info" of the next disk, psz3
2338 * contains a pointer to the file-path of the current cabinet, setID
2339 * contains an arbitrary constant associated with this set of cabinet files,
2340 * and iCabinet contains the numerical index of the current cabinet within
2341 * that set. Return zero, or -1 to abort.
2343 * fdintPARTIAL_FILE:
2345 * This notification is provided when FDICopy encounters a part of a file
2346 * contained in this cabinet which is missing its beginning. Files can be
2347 * split across cabinets, so this is not necessarily an abnormality; it just
2348 * means that the file in question begins in another cabinet. No file
2349 * corresponding to this notification is extracted from the cabinet. In the
2350 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2351 * partial file, psz2 contains a pointer to the file name of the cabinet in
2352 * which this file begins, and psz3 contains a pointer to the disk name or
2353 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2355 * fdintCOPY_FILE:
2357 * This notification is provided when FDICopy encounters a file which starts
2358 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2359 * look for files in cabinets after the first one). One notification will be
2360 * sent for each such file, before the file is decompressed. By returning
2361 * zero, the callback can instruct FDICopy to skip the file. In the structure
2362 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2363 * the size of the file (uncompressed), attribs contains the file attributes,
2364 * and date and time contain the date and time of the file. attributes, date,
2365 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2366 * for the entire cabinet, 0 to skip just this file but continue scanning the
2367 * cabinet for more files, or an FDIClose()-compatible file-handle.
2369 * fdintCLOSE_FILE_INFO:
2371 * This notification is important, don't forget to implement it. This
2372 * notification indicates that a file has been successfully uncompressed and
2373 * written to disk. Upon receipt of this notification, the callee is expected
2374 * to close the file handle, to set the attributes and date/time of the
2375 * closed file, and possibly to execute the file. In the structure pointed to
2376 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2377 * open file handle (close it), cb contains 1 or zero, indicating respectively
2378 * that the callee should or should not execute the file, and date, time
2379 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2380 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2381 * do so. Return TRUE, or FALSE to abort decompression.
2383 * fdintNEXT_CABINET:
2385 * This notification is called when FDICopy must load in another cabinet. This
2386 * can occur when a file's data is "split" across multiple cabinets. The
2387 * callee has the opportunity to request that FDICopy look in a different file
2388 * path for the specified cabinet file, by writing that data into a provided
2389 * buffer (see below for more information). This notification will be received
2390 * more than once per-cabinet in the instance that FDICopy failed to find a
2391 * valid cabinet at the location specified by the first per-cabinet
2392 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2393 * structure pointed to by pfdin indicates the error which prevented FDICopy
2394 * from proceeding successfully. Return zero to indicate success, or -1 to
2395 * indicate failure and abort FDICopy.
2397 * Upon receipt of this notification, the structure pointed to by pfdin will
2398 * contain the following values: psz1 pointing to the name of the cabinet
2399 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2400 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2401 * and fdie containing either FDIERROR_NONE, or one of the following:
2403 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2404 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2405 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2406 * FDIERROR_WRONG_CABINET.
2408 * The callee may choose to change the path where FDICopy will look for the
2409 * cabinet after this notification. To do so, the caller may write the new
2410 * pathname to the buffer pointed to by psz3, which is 256 characters in
2411 * length, including the terminating null character, before returning zero.
2413 * fdintENUMERATE:
2415 * Undocumented and unimplemented in wine, this seems to be sent each time
2416 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2417 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2418 * provides information about the current cabinet instead of the next one....
2419 * this is just a guess, it has not been looked at closely.
2421 * INCLUDES
2422 * fdi.c
2424 BOOL __cdecl FDICopy(
2425 HFDI hfdi,
2426 char *pszCabinet,
2427 char *pszCabPath,
2428 int flags,
2429 PFNFDINOTIFY pfnfdin,
2430 PFNFDIDECRYPT pfnfdid,
2431 void *pvUser)
2433 FDICABINETINFO fdici;
2434 FDINOTIFICATION fdin;
2435 int cabhf, filehf = 0, idx;
2436 unsigned int i;
2437 char fullpath[MAX_PATH];
2438 size_t pathlen, filenamelen;
2439 char emptystring = '\0';
2440 cab_UBYTE buf[64];
2441 struct fdi_folder *fol = NULL, *linkfol = NULL;
2442 struct fdi_file *file = NULL, *linkfile = NULL;
2443 fdi_decomp_state _decomp_state;
2444 fdi_decomp_state *decomp_state = &_decomp_state;
2446 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, "
2447 "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2448 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2450 if (!REALLY_IS_FDI(hfdi)) {
2451 SetLastError(ERROR_INVALID_HANDLE);
2452 return FALSE;
2455 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2457 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2458 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2460 /* slight overestimation here to save CPU cycles in the developer's brain */
2461 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2462 ERR("MAX_PATH exceeded.\n");
2463 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2464 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2465 PFDI_INT(hfdi)->perf->fError = TRUE;
2466 SetLastError(ERROR_FILE_NOT_FOUND);
2467 return FALSE;
2470 /* paste the path and filename together */
2471 idx = 0;
2472 if (pathlen) {
2473 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2474 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2476 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2477 fullpath[idx] = '\0';
2479 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2481 /* get a handle to the cabfile */
2482 cabhf = PFDI_OPEN(hfdi, fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2483 if (cabhf == -1) {
2484 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2485 PFDI_INT(hfdi)->perf->fError = TRUE;
2486 SetLastError(ERROR_FILE_NOT_FOUND);
2487 return FALSE;
2490 if (cabhf == 0) {
2491 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2492 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2493 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2494 PFDI_INT(hfdi)->perf->fError = TRUE;
2495 SetLastError(ERROR_FILE_NOT_FOUND);
2496 return FALSE;
2499 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2500 if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2501 ERR("FDIIsCabinet failed.\n");
2502 PFDI_CLOSE(hfdi, cabhf);
2503 return FALSE;
2506 /* cabinet notification */
2507 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2508 fdin.setID = fdici.setID;
2509 fdin.iCabinet = fdici.iCabinet;
2510 fdin.pv = pvUser;
2511 fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2512 fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2513 fdin.psz3 = pszCabPath;
2515 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2516 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2517 PFDI_INT(hfdi)->perf->erfType = 0;
2518 PFDI_INT(hfdi)->perf->fError = TRUE;
2519 goto bail_and_fail;
2522 CAB(setID) = fdici.setID;
2523 CAB(iCabinet) = fdici.iCabinet;
2524 CAB(cabhf) = cabhf;
2526 /* read folders */
2527 for (i = 0; i < fdici.cFolders; i++) {
2528 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2529 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2530 PFDI_INT(hfdi)->perf->erfType = 0;
2531 PFDI_INT(hfdi)->perf->fError = TRUE;
2532 goto bail_and_fail;
2535 if (CAB(mii).folder_resv > 0)
2536 PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2538 fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2539 if (!fol) {
2540 ERR("out of memory!\n");
2541 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2542 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2543 PFDI_INT(hfdi)->perf->fError = TRUE;
2544 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2545 goto bail_and_fail;
2547 ZeroMemory(fol, sizeof(struct fdi_folder));
2548 if (!CAB(firstfol)) CAB(firstfol) = fol;
2550 fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2551 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2552 fol->comp_type = EndGetI16(buf+cffold_CompType);
2554 if (linkfol)
2555 linkfol->next = fol;
2556 linkfol = fol;
2559 /* read files */
2560 for (i = 0; i < fdici.cFiles; i++) {
2561 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2562 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2563 PFDI_INT(hfdi)->perf->erfType = 0;
2564 PFDI_INT(hfdi)->perf->fError = TRUE;
2565 goto bail_and_fail;
2568 file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2569 if (!file) {
2570 ERR("out of memory!\n");
2571 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2572 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2573 PFDI_INT(hfdi)->perf->fError = TRUE;
2574 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2575 goto bail_and_fail;
2577 ZeroMemory(file, sizeof(struct fdi_file));
2578 if (!CAB(firstfile)) CAB(firstfile) = file;
2580 file->length = EndGetI32(buf+cffile_UncompressedSize);
2581 file->offset = EndGetI32(buf+cffile_FolderOffset);
2582 file->index = EndGetI16(buf+cffile_FolderIndex);
2583 file->time = EndGetI16(buf+cffile_Time);
2584 file->date = EndGetI16(buf+cffile_Date);
2585 file->attribs = EndGetI16(buf+cffile_Attribs);
2586 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2588 if (!file->filename) {
2589 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2590 PFDI_INT(hfdi)->perf->erfType = 0;
2591 PFDI_INT(hfdi)->perf->fError = TRUE;
2592 goto bail_and_fail;
2595 if (linkfile)
2596 linkfile->next = file;
2597 linkfile = file;
2600 for (file = CAB(firstfile); (file); file = file->next) {
2603 * FIXME: This implementation keeps multiple cabinet files open at once
2604 * when encountering a split cabinet. It is a quirk of this implementation
2605 * that sometimes we decrypt the same block of data more than once, to find
2606 * the right starting point for a file, moving the file-pointer backwards.
2607 * If we kept a cache of certain file-pointer information, we could eliminate
2608 * that behavior... in fact I am not sure that the caching we already have
2609 * is not sufficient.
2611 * The current implementation seems to work fine in straightforward situations
2612 * where all the cabinet files needed for decryption are simultaneously
2613 * available. But presumably, the API is supposed to support cabinets which
2614 * are split across multiple CDROMS; we may need to change our implementation
2615 * to strictly serialize it's file usage so that it opens only one cabinet
2616 * at a time. Some experimentation with Windows is needed to figure out the
2617 * precise semantics required. The relevant code is here and in fdi_decomp().
2620 /* partial-file notification */
2621 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2623 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2624 * and perform some tests to figure out the right behavior. The SDK says
2625 * FDICopy will notify the user of the filename and "disk name" (info) of
2626 * the cabinet where the spanning file /started/.
2628 * That would certainly be convenient for the API-user, who could abort,
2629 * everything (or parallelize, if that's allowed (it is in wine)), and call
2630 * FDICopy again with the provided filename, so as to avoid partial file
2631 * notification and successfully unpack. This task could be quite unpleasant
2632 * from wine's perspective: the information specifying the "start cabinet" for
2633 * a file is associated nowhere with the file header and is not to be found in
2634 * the cabinet header. We have only the index of the cabinet wherein the folder
2635 * begins, which contains the file. To find that cabinet, we must consider the
2636 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2637 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2638 * list).
2640 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2641 * cabinet other than the active one might be at another filepath than the
2642 * current one, or on another CDROM. This could get rather dicey, especially
2643 * if we imagine parallelized access to the FDICopy API.
2645 * The current implementation punts -- it just returns the previous cabinet and
2646 * it's info from the header of this cabinet. This provides the right answer in
2647 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2648 * we "fix" it.
2650 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2651 fdin.pv = pvUser;
2652 fdin.psz1 = (char *)file->filename;
2653 fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2654 fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2656 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2657 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2658 PFDI_INT(hfdi)->perf->erfType = 0;
2659 PFDI_INT(hfdi)->perf->fError = TRUE;
2660 goto bail_and_fail;
2662 /* I don't think we are supposed to decompress partial files. This prevents it. */
2663 file->oppressed = TRUE;
2665 if (file->oppressed) {
2666 filehf = 0;
2667 } else {
2668 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2669 fdin.pv = pvUser;
2670 fdin.psz1 = (char *)file->filename;
2671 fdin.cb = file->length;
2672 fdin.date = file->date;
2673 fdin.time = file->time;
2674 fdin.attribs = file->attribs;
2675 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2676 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2677 PFDI_INT(hfdi)->perf->erfType = 0;
2678 PFDI_INT(hfdi)->perf->fError = TRUE;
2679 filehf = 0;
2680 goto bail_and_fail;
2684 /* find the folder for this file if necc. */
2685 if (filehf) {
2686 int i2;
2688 fol = CAB(firstfol);
2689 if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2690 /* pick the last folder */
2691 while (fol->next) fol = fol->next;
2692 } else {
2693 for (i2 = 0; (i2 < file->index); i2++)
2694 if (fol->next) /* bug resistance, should always be true */
2695 fol = fol->next;
2699 if (filehf) {
2700 cab_UWORD comptype = fol->comp_type;
2701 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2702 int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2703 int err = 0;
2705 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2707 /* set up decomp_state */
2708 CAB(hfdi) = hfdi;
2709 CAB(filehf) = filehf;
2711 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2712 if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2714 TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2716 /* free stuff for the old decompresser */
2717 switch (ct2) {
2718 case cffoldCOMPTYPE_LZX:
2719 if (LZX(window)) {
2720 PFDI_FREE(hfdi, LZX(window));
2721 LZX(window) = NULL;
2723 break;
2724 case cffoldCOMPTYPE_QUANTUM:
2725 if (QTM(window)) {
2726 PFDI_FREE(hfdi, QTM(window));
2727 QTM(window) = NULL;
2729 break;
2732 CAB(decomp_cab) = NULL;
2733 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2734 CAB(offset) = 0;
2735 CAB(outlen) = 0;
2737 /* initialize the new decompresser */
2738 switch (ct1) {
2739 case cffoldCOMPTYPE_NONE:
2740 CAB(decompress) = NONEfdi_decomp;
2741 break;
2742 case cffoldCOMPTYPE_MSZIP:
2743 CAB(decompress) = ZIPfdi_decomp;
2744 break;
2745 case cffoldCOMPTYPE_QUANTUM:
2746 CAB(decompress) = QTMfdi_decomp;
2747 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2748 break;
2749 case cffoldCOMPTYPE_LZX:
2750 CAB(decompress) = LZXfdi_decomp;
2751 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2752 break;
2753 default:
2754 err = DECR_DATAFORMAT;
2758 CAB(current) = fol;
2760 switch (err) {
2761 case DECR_OK:
2762 break;
2763 case DECR_NOMEMORY:
2764 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2765 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2766 PFDI_INT(hfdi)->perf->fError = TRUE;
2767 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2768 goto bail_and_fail;
2769 default:
2770 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2771 PFDI_INT(hfdi)->perf->erfOper = 0;
2772 PFDI_INT(hfdi)->perf->fError = TRUE;
2773 goto bail_and_fail;
2776 if (file->offset > CAB(offset)) {
2777 /* decode bytes and send them to /dev/null */
2778 switch ((err = fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser))) {
2779 case DECR_OK:
2780 break;
2781 case DECR_USERABORT:
2782 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2783 PFDI_INT(hfdi)->perf->erfType = 0;
2784 PFDI_INT(hfdi)->perf->fError = TRUE;
2785 goto bail_and_fail;
2786 case DECR_NOMEMORY:
2787 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2788 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2789 PFDI_INT(hfdi)->perf->fError = TRUE;
2790 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2791 goto bail_and_fail;
2792 default:
2793 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2794 PFDI_INT(hfdi)->perf->erfOper = 0;
2795 PFDI_INT(hfdi)->perf->fError = TRUE;
2796 goto bail_and_fail;
2798 CAB(offset) = file->offset;
2801 /* now do the actual decompression */
2802 err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2803 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2805 /* fdintCLOSE_FILE_INFO notification */
2806 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2807 fdin.pv = pvUser;
2808 fdin.psz1 = (char *)file->filename;
2809 fdin.hf = filehf;
2810 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2811 fdin.date = file->date;
2812 fdin.time = file->time;
2813 fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2814 ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2815 filehf = 0;
2817 switch (err) {
2818 case DECR_OK:
2819 break;
2820 case DECR_USERABORT:
2821 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2822 PFDI_INT(hfdi)->perf->erfType = 0;
2823 PFDI_INT(hfdi)->perf->fError = TRUE;
2824 goto bail_and_fail;
2825 case DECR_NOMEMORY:
2826 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2827 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2828 PFDI_INT(hfdi)->perf->fError = TRUE;
2829 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2830 goto bail_and_fail;
2831 default:
2832 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2833 PFDI_INT(hfdi)->perf->erfOper = 0;
2834 PFDI_INT(hfdi)->perf->fError = TRUE;
2835 goto bail_and_fail;
2840 /* free decompression temps */
2841 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2842 case cffoldCOMPTYPE_LZX:
2843 if (LZX(window)) {
2844 PFDI_FREE(hfdi, LZX(window));
2845 LZX(window) = NULL;
2847 break;
2848 case cffoldCOMPTYPE_QUANTUM:
2849 if (QTM(window)) {
2850 PFDI_FREE(hfdi, QTM(window));
2851 QTM(window) = NULL;
2853 break;
2856 while (decomp_state) {
2857 fdi_decomp_state *prev_fds;
2859 PFDI_CLOSE(hfdi, CAB(cabhf));
2861 /* free the storage remembered by mii */
2862 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2863 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2864 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2865 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2867 while (CAB(firstfol)) {
2868 fol = CAB(firstfol);
2869 CAB(firstfol) = CAB(firstfol)->next;
2870 PFDI_FREE(hfdi, fol);
2872 while (CAB(firstfile)) {
2873 file = CAB(firstfile);
2874 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2875 CAB(firstfile) = CAB(firstfile)->next;
2876 PFDI_FREE(hfdi, file);
2878 prev_fds = decomp_state;
2879 decomp_state = CAB(next);
2880 if (prev_fds != &_decomp_state)
2881 PFDI_FREE(hfdi, prev_fds);
2884 return TRUE;
2886 bail_and_fail: /* here we free ram before error returns */
2888 /* free decompression temps */
2889 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2890 case cffoldCOMPTYPE_LZX:
2891 if (LZX(window)) {
2892 PFDI_FREE(hfdi, LZX(window));
2893 LZX(window) = NULL;
2895 break;
2896 case cffoldCOMPTYPE_QUANTUM:
2897 if (QTM(window)) {
2898 PFDI_FREE(hfdi, QTM(window));
2899 QTM(window) = NULL;
2901 break;
2904 if (filehf) PFDI_CLOSE(hfdi, filehf);
2906 while (decomp_state) {
2907 fdi_decomp_state *prev_fds;
2909 PFDI_CLOSE(hfdi, CAB(cabhf));
2911 /* free the storage remembered by mii */
2912 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2913 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2914 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2915 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2917 while (CAB(firstfol)) {
2918 fol = CAB(firstfol);
2919 CAB(firstfol) = CAB(firstfol)->next;
2920 PFDI_FREE(hfdi, fol);
2922 while (CAB(firstfile)) {
2923 file = CAB(firstfile);
2924 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2925 CAB(firstfile) = CAB(firstfile)->next;
2926 PFDI_FREE(hfdi, file);
2928 prev_fds = decomp_state;
2929 decomp_state = CAB(next);
2930 if (prev_fds != &_decomp_state)
2931 PFDI_FREE(hfdi, prev_fds);
2934 return FALSE;
2937 /***********************************************************************
2938 * FDIDestroy (CABINET.23)
2940 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2941 * of FDICopy. Only reason for failure would be an invalid handle.
2943 * PARAMS
2944 * hfdi [I] The HFDI to free
2946 * RETURNS
2947 * TRUE for success
2948 * FALSE for failure
2950 BOOL __cdecl FDIDestroy(HFDI hfdi)
2952 TRACE("(hfdi == ^%p)\n", hfdi);
2953 if (REALLY_IS_FDI(hfdi)) {
2954 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2955 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2956 return TRUE;
2957 } else {
2958 SetLastError(ERROR_INVALID_HANDLE);
2959 return FALSE;
2963 /***********************************************************************
2964 * FDITruncateCabinet (CABINET.24)
2966 * Removes all folders of a cabinet file after and including the
2967 * specified folder number.
2969 * PARAMS
2970 * hfdi [I] Handle to the FDI context.
2971 * pszCabinetName [I] Filename of the cabinet.
2972 * iFolderToDelete [I] Index of the first folder to delete.
2974 * RETURNS
2975 * Success: TRUE.
2976 * Failure: FALSE.
2978 * NOTES
2979 * The PFNWRITE function supplied to FDICreate must truncate the
2980 * file at the current position if the number of bytes to write is 0.
2982 BOOL __cdecl FDITruncateCabinet(
2983 HFDI hfdi,
2984 char *pszCabinetName,
2985 USHORT iFolderToDelete)
2987 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2988 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2990 if (!REALLY_IS_FDI(hfdi)) {
2991 SetLastError(ERROR_INVALID_HANDLE);
2992 return FALSE;
2995 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2996 return FALSE;