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