push 0661da64275a0e67e1a41492b8d7716e364e773c
[wine/hacks.git] / dlls / cabinet / fdi.c
blob09d0fe7bc516b8dc94c28875a4ab35578b0cfa81
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 void QTMupdatemodel(struct QTMmodel *model, int sym) {
155 struct QTMmodelsym temp;
156 int i, j;
158 for (i = 0; i < sym; i++) model->syms[i].cumfreq += 8;
160 if (model->syms[0].cumfreq > 3800) {
161 if (--model->shiftsleft) {
162 for (i = model->entries - 1; i >= 0; i--) {
163 /* -1, not -2; the 0 entry saves this */
164 model->syms[i].cumfreq >>= 1;
165 if (model->syms[i].cumfreq <= model->syms[i+1].cumfreq) {
166 model->syms[i].cumfreq = model->syms[i+1].cumfreq + 1;
170 else {
171 model->shiftsleft = 50;
172 for (i = 0; i < model->entries ; i++) {
173 /* no -1, want to include the 0 entry */
174 /* this converts cumfreqs into frequencies, then shifts right */
175 model->syms[i].cumfreq -= model->syms[i+1].cumfreq;
176 model->syms[i].cumfreq++; /* avoid losing things entirely */
177 model->syms[i].cumfreq >>= 1;
180 /* now sort by frequencies, decreasing order -- this must be an
181 * inplace selection sort, or a sort with the same (in)stability
182 * characteristics
184 for (i = 0; i < model->entries - 1; i++) {
185 for (j = i + 1; j < model->entries; j++) {
186 if (model->syms[i].cumfreq < model->syms[j].cumfreq) {
187 temp = model->syms[i];
188 model->syms[i] = model->syms[j];
189 model->syms[j] = temp;
194 /* then convert frequencies back to cumfreq */
195 for (i = model->entries - 1; i >= 0; i--) {
196 model->syms[i].cumfreq += model->syms[i+1].cumfreq;
198 /* then update the other part of the table */
199 for (i = 0; i < model->entries; i++) {
200 model->tabloc[model->syms[i].sym] = i;
206 /*************************************************************************
207 * make_decode_table (internal)
209 * This function was coded by David Tritscher. It builds a fast huffman
210 * decoding table out of just a canonical huffman code lengths table.
212 * PARAMS
213 * nsyms: total number of symbols in this huffman tree.
214 * nbits: any symbols with a code length of nbits or less can be decoded
215 * in one lookup of the table.
216 * length: A table to get code lengths from [0 to syms-1]
217 * table: The table to fill up with decoded symbols and pointers.
219 * RETURNS
220 * OK: 0
221 * error: 1
223 int make_decode_table(cab_ULONG nsyms, cab_ULONG nbits, const cab_UBYTE *length, cab_UWORD *table) {
224 register cab_UWORD sym;
225 register cab_ULONG leaf;
226 register cab_UBYTE bit_num = 1;
227 cab_ULONG fill;
228 cab_ULONG pos = 0; /* the current position in the decode table */
229 cab_ULONG table_mask = 1 << nbits;
230 cab_ULONG bit_mask = table_mask >> 1; /* don't do 0 length codes */
231 cab_ULONG next_symbol = bit_mask; /* base of allocation for long codes */
233 /* fill entries for codes short enough for a direct mapping */
234 while (bit_num <= nbits) {
235 for (sym = 0; sym < nsyms; sym++) {
236 if (length[sym] == bit_num) {
237 leaf = pos;
239 if((pos += bit_mask) > table_mask) return 1; /* table overrun */
241 /* fill all possible lookups of this symbol with the symbol itself */
242 fill = bit_mask;
243 while (fill-- > 0) table[leaf++] = sym;
246 bit_mask >>= 1;
247 bit_num++;
250 /* if there are any codes longer than nbits */
251 if (pos != table_mask) {
252 /* clear the remainder of the table */
253 for (sym = pos; sym < table_mask; sym++) table[sym] = 0;
255 /* give ourselves room for codes to grow by up to 16 more bits */
256 pos <<= 16;
257 table_mask <<= 16;
258 bit_mask = 1 << 15;
260 while (bit_num <= 16) {
261 for (sym = 0; sym < nsyms; sym++) {
262 if (length[sym] == bit_num) {
263 leaf = pos >> 16;
264 for (fill = 0; fill < bit_num - nbits; fill++) {
265 /* if this path hasn't been taken yet, 'allocate' two entries */
266 if (table[leaf] == 0) {
267 table[(next_symbol << 1)] = 0;
268 table[(next_symbol << 1) + 1] = 0;
269 table[leaf] = next_symbol++;
271 /* follow the path and select either left or right for next bit */
272 leaf = table[leaf] << 1;
273 if ((pos >> (15-fill)) & 1) leaf++;
275 table[leaf] = sym;
277 if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
280 bit_mask >>= 1;
281 bit_num++;
285 /* full table? */
286 if (pos == table_mask) return 0;
288 /* either erroneous table, or all elements are 0 - let's find out. */
289 for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1;
290 return 0;
293 /*************************************************************************
294 * checksum (internal)
296 cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum) {
297 int len;
298 cab_ULONG ul = 0;
300 for (len = bytes >> 2; len--; data += 4) {
301 csum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
304 switch (bytes & 3) {
305 case 3: ul |= *data++ << 16;
306 case 2: ul |= *data++ << 8;
307 case 1: ul |= *data;
309 csum ^= ul;
311 return csum;
314 /***********************************************************************
315 * FDICreate (CABINET.20)
317 * Provided with several callbacks (all of them are mandatory),
318 * returns a handle which can be used to perform operations
319 * on cabinet files.
321 * PARAMS
322 * pfnalloc [I] A pointer to a function which allocates ram. Uses
323 * the same interface as malloc.
324 * pfnfree [I] A pointer to a function which frees ram. Uses the
325 * same interface as free.
326 * pfnopen [I] A pointer to a function which opens a file. Uses
327 * the same interface as _open.
328 * pfnread [I] A pointer to a function which reads from a file into
329 * a caller-provided buffer. Uses the same interface
330 * as _read
331 * pfnwrite [I] A pointer to a function which writes to a file from
332 * a caller-provided buffer. Uses the same interface
333 * as _write.
334 * pfnclose [I] A pointer to a function which closes a file handle.
335 * Uses the same interface as _close.
336 * pfnseek [I] A pointer to a function which seeks in a file.
337 * Uses the same interface as _lseek.
338 * cpuType [I] The type of CPU; ignored in wine (recommended value:
339 * cpuUNKNOWN, aka -1).
340 * perf [IO] A pointer to an ERF structure. When FDICreate
341 * returns an error condition, error information may
342 * be found here as well as from GetLastError.
344 * RETURNS
345 * On success, returns an FDI handle of type HFDI.
346 * On failure, the NULL file handle is returned. Error
347 * info can be retrieved from perf.
349 * INCLUDES
350 * fdi.h
353 HFDI __cdecl FDICreate(
354 PFNALLOC pfnalloc,
355 PFNFREE pfnfree,
356 PFNOPEN pfnopen,
357 PFNREAD pfnread,
358 PFNWRITE pfnwrite,
359 PFNCLOSE pfnclose,
360 PFNSEEK pfnseek,
361 int cpuType,
362 PERF perf)
364 HFDI rv;
366 TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, "
367 "pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
368 pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
369 cpuType, perf);
371 if ((!pfnalloc) || (!pfnfree)) {
372 perf->erfOper = FDIERROR_NONE;
373 perf->erfType = ERROR_BAD_ARGUMENTS;
374 perf->fError = TRUE;
376 SetLastError(ERROR_BAD_ARGUMENTS);
377 return NULL;
380 if (!((rv = (*pfnalloc)(sizeof(FDI_Int))))) {
381 perf->erfOper = FDIERROR_ALLOC_FAIL;
382 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
383 perf->fError = TRUE;
385 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
386 return NULL;
389 PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
390 PFDI_INT(rv)->pfnalloc = pfnalloc;
391 PFDI_INT(rv)->pfnfree = pfnfree;
392 PFDI_INT(rv)->pfnopen = pfnopen;
393 PFDI_INT(rv)->pfnread = pfnread;
394 PFDI_INT(rv)->pfnwrite = pfnwrite;
395 PFDI_INT(rv)->pfnclose = pfnclose;
396 PFDI_INT(rv)->pfnseek = pfnseek;
397 /* no-brainer: we ignore the cpu type; this is only used
398 for the 16-bit versions in Windows anyhow... */
399 PFDI_INT(rv)->perf = perf;
401 return rv;
404 /*******************************************************************
405 * FDI_getoffset (internal)
407 * returns the file pointer position of a file handle.
409 static long FDI_getoffset(HFDI hfdi, INT_PTR hf)
411 return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
414 /**********************************************************************
415 * FDI_read_string (internal)
417 * allocate and read an arbitrarily long string from the cabinet
419 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
421 size_t len=256,
422 base = FDI_getoffset(hfdi, hf),
423 maxlen = cabsize - base;
424 BOOL ok = FALSE;
425 unsigned int i;
426 cab_UBYTE *buf = NULL;
428 TRACE("(hfdi == ^%p, hf == %ld, cabsize == %ld)\n", hfdi, hf, cabsize);
430 do {
431 if (len > maxlen) len = maxlen;
432 if (!(buf = PFDI_ALLOC(hfdi, len))) break;
433 if (!PFDI_READ(hfdi, hf, buf, len)) break;
435 /* search for a null terminator in what we've just read */
436 for (i=0; i < len; i++) {
437 if (!buf[i]) {ok=TRUE; break;}
440 if (!ok) {
441 if (len == maxlen) {
442 ERR("cabinet is truncated\n");
443 break;
445 /* The buffer is too small for the string. Reset the file to the point
446 * were we started, free the buffer and increase the size for the next try
448 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
449 PFDI_FREE(hfdi, buf);
450 buf = NULL;
451 len *= 2;
453 } while (!ok);
455 if (!ok) {
456 if (buf)
457 PFDI_FREE(hfdi, buf);
458 else
459 ERR("out of memory!\n");
460 return NULL;
463 /* otherwise, set the stream to just after the string and return */
464 PFDI_SEEK(hfdi, hf, base + strlen((char *)buf) + 1, SEEK_SET);
466 return (char *) buf;
469 /******************************************************************
470 * FDI_read_entries (internal)
472 * process the cabinet header in the style of FDIIsCabinet, but
473 * without the sanity checks (and bug)
475 static BOOL FDI_read_entries(
476 HFDI hfdi,
477 INT_PTR hf,
478 PFDICABINETINFO pfdici,
479 PMORE_ISCAB_INFO pmii)
481 int num_folders, num_files, header_resv, folder_resv = 0;
482 LONG base_offset, cabsize;
483 USHORT setid, cabidx, flags;
484 cab_UBYTE buf[64], block_resv;
485 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
487 TRACE("(hfdi == ^%p, hf == %ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
490 * FIXME: I just noticed that I am memorizing the initial file pointer
491 * offset and restoring it before reading in the rest of the header
492 * information in the cabinet. Perhaps that's correct -- that is, perhaps
493 * this API is supposed to support "streaming" cabinets which are embedded
494 * in other files, or cabinets which begin at file offsets other than zero.
495 * Otherwise, I should instead go to the absolute beginning of the file.
496 * (Either way, the semantics of wine's FDICopy require me to leave the
497 * file pointer where it is afterwards -- If Windows does not do so, we
498 * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
500 * So, the answer lies in Windows; will native cabinet.dll recognize a
501 * cabinet "file" embedded in another file? Note that cabextract.c does
502 * support this, which implies that Microsoft's might. I haven't tried it
503 * yet so I don't know. ATM, most of wine's FDI cabinet routines (except
504 * this one) would not work in this way. To fix it, we could just make the
505 * various references to absolute file positions in the code relative to an
506 * initial "beginning" offset. Because the FDICopy API doesn't take a
507 * file-handle like this one, we would therein need to search through the
508 * file for the beginning of the cabinet (as we also do in cabextract.c).
509 * Note that this limits us to a maximum of one cabinet per. file: the first.
511 * So, in summary: either the code below is wrong, or the rest of fdi.c is
512 * wrong... I cannot imagine that both are correct ;) One of these flaws
513 * should be fixed after determining the behavior on Windows. We ought
514 * to check both FDIIsCabinet and FDICopy for the right behavior.
516 * -gmt
519 /* get basic offset & size info */
520 base_offset = FDI_getoffset(hfdi, hf);
522 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
523 if (pmii) {
524 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
525 PFDI_INT(hfdi)->perf->erfType = 0;
526 PFDI_INT(hfdi)->perf->fError = TRUE;
528 return FALSE;
531 cabsize = FDI_getoffset(hfdi, hf);
533 if ((cabsize == -1) || (base_offset == -1) ||
534 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
535 if (pmii) {
536 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
537 PFDI_INT(hfdi)->perf->erfType = 0;
538 PFDI_INT(hfdi)->perf->fError = TRUE;
540 return FALSE;
543 /* read in the CFHEADER */
544 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
545 if (pmii) {
546 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
547 PFDI_INT(hfdi)->perf->erfType = 0;
548 PFDI_INT(hfdi)->perf->fError = TRUE;
550 return FALSE;
553 /* check basic MSCF signature */
554 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
555 if (pmii) {
556 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
557 PFDI_INT(hfdi)->perf->erfType = 0;
558 PFDI_INT(hfdi)->perf->fError = TRUE;
560 return FALSE;
563 /* get the number of folders */
564 num_folders = EndGetI16(buf+cfhead_NumFolders);
565 if (num_folders == 0) {
566 /* PONDERME: is this really invalid? */
567 WARN("weird cabinet detect failure: no folders in cabinet\n");
568 if (pmii) {
569 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
570 PFDI_INT(hfdi)->perf->erfType = 0;
571 PFDI_INT(hfdi)->perf->fError = TRUE;
573 return FALSE;
576 /* get the number of files */
577 num_files = EndGetI16(buf+cfhead_NumFiles);
578 if (num_files == 0) {
579 /* PONDERME: is this really invalid? */
580 WARN("weird cabinet detect failure: no files in cabinet\n");
581 if (pmii) {
582 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
583 PFDI_INT(hfdi)->perf->erfType = 0;
584 PFDI_INT(hfdi)->perf->fError = TRUE;
586 return FALSE;
589 /* setid */
590 setid = EndGetI16(buf+cfhead_SetID);
592 /* cabinet (set) index */
593 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
595 /* check the header revision */
596 if ((buf[cfhead_MajorVersion] > 1) ||
597 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
599 WARN("cabinet format version > 1.3\n");
600 if (pmii) {
601 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
602 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
603 PFDI_INT(hfdi)->perf->fError = TRUE;
605 return FALSE;
608 /* pull the flags out */
609 flags = EndGetI16(buf+cfhead_Flags);
611 /* read the reserved-sizes part of header, if present */
612 if (flags & cfheadRESERVE_PRESENT) {
613 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
614 ERR("bunk reserve-sizes?\n");
615 if (pmii) {
616 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
617 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
618 PFDI_INT(hfdi)->perf->fError = TRUE;
620 return FALSE;
623 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
624 if (pmii) pmii->header_resv = header_resv;
625 folder_resv = buf[cfheadext_FolderReserved];
626 if (pmii) pmii->folder_resv = folder_resv;
627 block_resv = buf[cfheadext_DataReserved];
628 if (pmii) pmii->block_resv = block_resv;
630 if (header_resv > 60000) {
631 WARN("WARNING; header reserved space > 60000\n");
634 /* skip the reserved header */
635 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
636 ERR("seek failure: header_resv\n");
637 if (pmii) {
638 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
639 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
640 PFDI_INT(hfdi)->perf->fError = TRUE;
642 return FALSE;
646 if (flags & cfheadPREV_CABINET) {
647 prevname = FDI_read_string(hfdi, hf, cabsize);
648 if (!prevname) {
649 if (pmii) {
650 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
651 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
652 PFDI_INT(hfdi)->perf->fError = TRUE;
654 return FALSE;
655 } else
656 if (pmii)
657 pmii->prevname = prevname;
658 else
659 PFDI_FREE(hfdi, prevname);
660 previnfo = FDI_read_string(hfdi, hf, cabsize);
661 if (previnfo) {
662 if (pmii)
663 pmii->previnfo = previnfo;
664 else
665 PFDI_FREE(hfdi, previnfo);
669 if (flags & cfheadNEXT_CABINET) {
670 if (pmii)
671 pmii->hasnext = TRUE;
672 nextname = FDI_read_string(hfdi, hf, cabsize);
673 if (!nextname) {
674 if ((flags & cfheadPREV_CABINET) && pmii) {
675 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
676 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
678 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
679 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
680 PFDI_INT(hfdi)->perf->fError = TRUE;
681 return FALSE;
682 } else
683 if (pmii)
684 pmii->nextname = nextname;
685 else
686 PFDI_FREE(hfdi, nextname);
687 nextinfo = FDI_read_string(hfdi, hf, cabsize);
688 if (nextinfo) {
689 if (pmii)
690 pmii->nextinfo = nextinfo;
691 else
692 PFDI_FREE(hfdi, nextinfo);
696 /* we could process the whole cabinet searching for problems;
697 instead lets stop here. Now let's fill out the paperwork */
698 pfdici->cbCabinet = cabsize;
699 pfdici->cFolders = num_folders;
700 pfdici->cFiles = num_files;
701 pfdici->setID = setid;
702 pfdici->iCabinet = cabidx;
703 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
704 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
705 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
706 return TRUE;
709 /***********************************************************************
710 * FDIIsCabinet (CABINET.21)
712 * Informs the caller as to whether or not the provided file handle is
713 * really a cabinet or not, filling out the provided PFDICABINETINFO
714 * structure with information about the cabinet. Brief explanations of
715 * the elements of this structure are available as comments accompanying
716 * its definition in wine's include/fdi.h.
718 * PARAMS
719 * hfdi [I] An HFDI from FDICreate
720 * hf [I] The file handle about which the caller inquires
721 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
722 * be filled out with information about the cabinet
723 * file indicated by hf if, indeed, it is determined
724 * to be a cabinet.
726 * RETURNS
727 * TRUE if the file is a cabinet. The info pointed to by pfdici will
728 * be provided.
729 * FALSE if the file is not a cabinet, or if an error was encountered
730 * while processing the cabinet. The PERF structure provided to
731 * FDICreate can be queried for more error information.
733 * INCLUDES
734 * fdi.c
736 BOOL __cdecl FDIIsCabinet(
737 HFDI hfdi,
738 INT_PTR hf,
739 PFDICABINETINFO pfdici)
741 BOOL rv;
743 TRACE("(hfdi == ^%p, hf == ^%ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
745 if (!REALLY_IS_FDI(hfdi)) {
746 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
747 SetLastError(ERROR_INVALID_HANDLE);
748 return FALSE;
751 if (!hf) {
752 ERR("(!hf)!\n");
753 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
754 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
755 PFDI_INT(hfdi)->perf->fError = TRUE; */
756 SetLastError(ERROR_INVALID_HANDLE);
757 return FALSE;
760 if (!pfdici) {
761 ERR("(!pfdici)!\n");
762 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
763 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
764 PFDI_INT(hfdi)->perf->fError = TRUE; */
765 SetLastError(ERROR_BAD_ARGUMENTS);
766 return FALSE;
768 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
770 if (rv)
771 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
773 return rv;
776 /******************************************************************
777 * QTMfdi_initmodel (internal)
779 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
781 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
782 int i;
783 m->shiftsleft = 4;
784 m->entries = n;
785 m->syms = sym;
786 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
787 for (i = 0; i < n; i++) {
788 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
789 m->syms[i].sym = i+s; /* actual symbol */
790 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
792 m->syms[n].cumfreq = 0;
795 /******************************************************************
796 * QTMfdi_init (internal)
798 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
799 unsigned int wndsize = 1 << window;
800 int msz = window * 2, i;
801 cab_ULONG j;
803 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
804 /* if a previously allocated window is big enough, keep it */
805 if (window < 10 || window > 21) return DECR_DATAFORMAT;
806 if (QTM(actual_size) < wndsize) {
807 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
808 QTM(window) = NULL;
810 if (!QTM(window)) {
811 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
812 QTM(actual_size) = wndsize;
814 QTM(window_size) = wndsize;
815 QTM(window_posn) = 0;
817 /* initialize static slot/extrabits tables */
818 for (i = 0, j = 0; i < 27; i++) {
819 CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
820 CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
822 for (i = 0, j = 0; i < 42; i++) {
823 CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
824 CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
827 /* initialize arithmetic coding models */
829 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
831 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
832 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
833 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
834 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
836 /* model 4 depends on table size, ranges from 20 to 24 */
837 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
838 /* model 5 depends on table size, ranges from 20 to 36 */
839 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
840 /* model 6pos depends on table size, ranges from 20 to 42 */
841 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
842 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
844 return DECR_OK;
847 /************************************************************
848 * LZXfdi_init (internal)
850 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
851 static const cab_UBYTE bits[] =
852 { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
853 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
854 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
855 17, 17, 17};
856 static const cab_ULONG base[] =
857 { 0, 1, 2, 3, 4, 6, 8, 12,
858 16, 24, 32, 48, 64, 96, 128, 192,
859 256, 384, 512, 768, 1024, 1536, 2048, 3072,
860 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
861 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
862 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
863 1835008, 1966080, 2097152};
864 cab_ULONG wndsize = 1 << window;
865 int posn_slots;
867 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
868 /* if a previously allocated window is big enough, keep it */
869 if (window < 15 || window > 21) return DECR_DATAFORMAT;
870 if (LZX(actual_size) < wndsize) {
871 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
872 LZX(window) = NULL;
874 if (!LZX(window)) {
875 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
876 LZX(actual_size) = wndsize;
878 LZX(window_size) = wndsize;
880 /* initialize static tables */
881 memcpy(CAB(extra_bits), bits, sizeof(bits));
882 memcpy(CAB(lzx_position_base), base, sizeof(base));
884 /* calculate required position slots */
885 if (window == 20) posn_slots = 42;
886 else if (window == 21) posn_slots = 50;
887 else posn_slots = window << 1;
889 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
891 LZX(R0) = LZX(R1) = LZX(R2) = 1;
892 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
893 LZX(header_read) = 0;
894 LZX(frames_read) = 0;
895 LZX(block_remaining) = 0;
896 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
897 LZX(intel_curpos) = 0;
898 LZX(intel_started) = 0;
899 LZX(window_posn) = 0;
901 /* initialize tables to 0 (because deltas will be applied to them) */
902 memset(LZX(MAINTREE_len), 0, sizeof(LZX(MAINTREE_len)));
903 memset(LZX(LENGTH_len), 0, sizeof(LZX(LENGTH_len)));
905 return DECR_OK;
908 /****************************************************
909 * NONEfdi_decomp(internal)
911 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
913 if (inlen != outlen) return DECR_ILLEGALDATA;
914 if (outlen > CAB_BLOCKMAX) return DECR_DATAFORMAT;
915 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
916 return DECR_OK;
919 /********************************************************
920 * Ziphuft_free (internal)
922 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
924 register struct Ziphuft *p, *q;
926 /* Go through linked list, freeing from the allocated (t[-1]) address. */
927 p = t;
928 while (p != NULL)
930 q = (--p)->v.t;
931 PFDI_FREE(hfdi, p);
932 p = q;
936 /*********************************************************
937 * fdi_Ziphuft_build (internal)
939 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, const cab_UWORD *d, const cab_UWORD *e,
940 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
942 cab_ULONG a; /* counter for codes of length k */
943 cab_ULONG el; /* length of EOB code (value 256) */
944 cab_ULONG f; /* i repeats in table every f entries */
945 cab_LONG g; /* maximum code length */
946 cab_LONG h; /* table level */
947 register cab_ULONG i; /* counter, current code */
948 register cab_ULONG j; /* counter */
949 register cab_LONG k; /* number of bits in current code */
950 cab_LONG *l; /* stack of bits per table */
951 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
952 register struct Ziphuft *q; /* points to current table */
953 struct Ziphuft r; /* table entry for structure assignment */
954 register cab_LONG w; /* bits before this table == (l * h) */
955 cab_ULONG *xp; /* pointer into x */
956 cab_LONG y; /* number of dummy codes added */
957 cab_ULONG z; /* number of entries in current table */
959 l = ZIP(lx)+1;
961 /* Generate counts for each bit length */
962 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
964 for(i = 0; i < ZIPBMAX+1; ++i)
965 ZIP(c)[i] = 0;
966 p = b; i = n;
969 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
970 } while (--i);
971 if (ZIP(c)[0] == n) /* null input--all zero length codes */
973 *t = NULL;
974 *m = 0;
975 return 0;
978 /* Find minimum and maximum length, bound *m by those */
979 for (j = 1; j <= ZIPBMAX; j++)
980 if (ZIP(c)[j])
981 break;
982 k = j; /* minimum code length */
983 if ((cab_ULONG)*m < j)
984 *m = j;
985 for (i = ZIPBMAX; i; i--)
986 if (ZIP(c)[i])
987 break;
988 g = i; /* maximum code length */
989 if ((cab_ULONG)*m > i)
990 *m = i;
992 /* Adjust last length count to fill out codes, if needed */
993 for (y = 1 << j; j < i; j++, y <<= 1)
994 if ((y -= ZIP(c)[j]) < 0)
995 return 2; /* bad input: more codes than bits */
996 if ((y -= ZIP(c)[i]) < 0)
997 return 2;
998 ZIP(c)[i] += y;
1000 /* Generate starting offsets LONGo the value table for each length */
1001 ZIP(x)[1] = j = 0;
1002 p = ZIP(c) + 1; xp = ZIP(x) + 2;
1003 while (--i)
1004 { /* note that i == g from above */
1005 *xp++ = (j += *p++);
1008 /* Make a table of values in order of bit lengths */
1009 p = b; i = 0;
1011 if ((j = *p++) != 0)
1012 ZIP(v)[ZIP(x)[j]++] = i;
1013 } while (++i < n);
1016 /* Generate the Huffman codes and for each, make the table entries */
1017 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
1018 p = ZIP(v); /* grab values in bit order */
1019 h = -1; /* no tables yet--level -1 */
1020 w = l[-1] = 0; /* no bits decoded yet */
1021 ZIP(u)[0] = NULL; /* just to keep compilers happy */
1022 q = NULL; /* ditto */
1023 z = 0; /* ditto */
1025 /* go through the bit lengths (k already is bits in shortest code) */
1026 for (; k <= g; k++)
1028 a = ZIP(c)[k];
1029 while (a--)
1031 /* here i is the Huffman code of length k bits for value *p */
1032 /* make tables up to required level */
1033 while (k > w + l[h])
1035 w += l[h++]; /* add bits already decoded */
1037 /* compute minimum size table less than or equal to *m bits */
1038 if ((z = g - w) > (cab_ULONG)*m) /* upper limit */
1039 z = *m;
1040 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
1041 { /* too few codes for k-w bit table */
1042 f -= a + 1; /* deduct codes from patterns left */
1043 xp = ZIP(c) + k;
1044 while (++j < z) /* try smaller tables up to z bits */
1046 if ((f <<= 1) <= *++xp)
1047 break; /* enough codes to use up j bits */
1048 f -= *xp; /* else deduct codes from patterns */
1051 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
1052 j = el - w; /* make EOB code end at table */
1053 z = 1 << j; /* table entries for j-bit table */
1054 l[h] = j; /* set table size in stack */
1056 /* allocate and link in new table */
1057 if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
1059 if(h)
1060 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
1061 return 3; /* not enough memory */
1063 *t = q + 1; /* link to list for Ziphuft_free() */
1064 *(t = &(q->v.t)) = NULL;
1065 ZIP(u)[h] = ++q; /* table starts after link */
1067 /* connect to last table, if there is one */
1068 if (h)
1070 ZIP(x)[h] = i; /* save pattern for backing up */
1071 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
1072 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
1073 r.v.t = q; /* pointer to this table */
1074 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
1075 ZIP(u)[h-1][j] = r; /* connect to last table */
1079 /* set up table entry in r */
1080 r.b = (cab_UBYTE)(k - w);
1081 if (p >= ZIP(v) + n)
1082 r.e = 99; /* out of values--invalid code */
1083 else if (*p < s)
1085 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
1086 r.v.n = *p++; /* simple code is just the value */
1088 else
1090 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
1091 r.v.n = d[*p++ - s];
1094 /* fill code-like entries with r */
1095 f = 1 << (k - w);
1096 for (j = i >> w; j < z; j += f)
1097 q[j] = r;
1099 /* backwards increment the k-bit code i */
1100 for (j = 1 << (k - 1); i & j; j >>= 1)
1101 i ^= j;
1102 i ^= j;
1104 /* backup over finished tables */
1105 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
1106 w -= l[--h]; /* don't need to update q */
1110 /* return actual size of base table */
1111 *m = l[0];
1113 /* Return true (1) if we were given an incomplete table */
1114 return y != 0 && g != 1;
1117 /*********************************************************
1118 * fdi_Zipinflate_codes (internal)
1120 static cab_LONG fdi_Zipinflate_codes(const struct Ziphuft *tl, const struct Ziphuft *td,
1121 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
1123 register cab_ULONG e; /* table entry flag/number of extra bits */
1124 cab_ULONG n, d; /* length and index for copy */
1125 cab_ULONG w; /* current window position */
1126 const struct Ziphuft *t; /* pointer to table entry */
1127 cab_ULONG ml, md; /* masks for bl and bd bits */
1128 register cab_ULONG b; /* bit buffer */
1129 register cab_ULONG k; /* number of bits in bit buffer */
1131 /* make local copies of globals */
1132 b = ZIP(bb); /* initialize bit buffer */
1133 k = ZIP(bk);
1134 w = ZIP(window_posn); /* initialize window position */
1136 /* inflate the coded data */
1137 ml = Zipmask[bl]; /* precompute masks for speed */
1138 md = Zipmask[bd];
1140 for(;;)
1142 ZIPNEEDBITS((cab_ULONG)bl)
1143 if((e = (t = tl + (b & ml))->e) > 16)
1146 if (e == 99)
1147 return 1;
1148 ZIPDUMPBITS(t->b)
1149 e -= 16;
1150 ZIPNEEDBITS(e)
1151 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1152 ZIPDUMPBITS(t->b)
1153 if (e == 16) /* then it's a literal */
1154 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
1155 else /* it's an EOB or a length */
1157 /* exit if end of block */
1158 if(e == 15)
1159 break;
1161 /* get length of block to copy */
1162 ZIPNEEDBITS(e)
1163 n = t->v.n + (b & Zipmask[e]);
1164 ZIPDUMPBITS(e);
1166 /* decode distance of block to copy */
1167 ZIPNEEDBITS((cab_ULONG)bd)
1168 if ((e = (t = td + (b & md))->e) > 16)
1169 do {
1170 if (e == 99)
1171 return 1;
1172 ZIPDUMPBITS(t->b)
1173 e -= 16;
1174 ZIPNEEDBITS(e)
1175 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1176 ZIPDUMPBITS(t->b)
1177 ZIPNEEDBITS(e)
1178 d = w - t->v.n - (b & Zipmask[e]);
1179 ZIPDUMPBITS(e)
1182 d &= ZIPWSIZE - 1;
1183 e = ZIPWSIZE - max(d, w);
1184 e = min(e, n);
1185 n -= e;
1188 CAB(outbuf)[w++] = CAB(outbuf)[d++];
1189 } while (--e);
1190 } while (n);
1194 /* restore the globals from the locals */
1195 ZIP(window_posn) = w; /* restore global window pointer */
1196 ZIP(bb) = b; /* restore global bit buffer */
1197 ZIP(bk) = k;
1199 /* done */
1200 return 0;
1203 /***********************************************************
1204 * Zipinflate_stored (internal)
1206 static cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1207 /* "decompress" an inflated type 0 (stored) block. */
1209 cab_ULONG n; /* number of bytes in block */
1210 cab_ULONG w; /* current window position */
1211 register cab_ULONG b; /* bit buffer */
1212 register cab_ULONG k; /* number of bits in bit buffer */
1214 /* make local copies of globals */
1215 b = ZIP(bb); /* initialize bit buffer */
1216 k = ZIP(bk);
1217 w = ZIP(window_posn); /* initialize window position */
1219 /* go to byte boundary */
1220 n = k & 7;
1221 ZIPDUMPBITS(n);
1223 /* get the length and its complement */
1224 ZIPNEEDBITS(16)
1225 n = (b & 0xffff);
1226 ZIPDUMPBITS(16)
1227 ZIPNEEDBITS(16)
1228 if (n != ((~b) & 0xffff))
1229 return 1; /* error in compressed data */
1230 ZIPDUMPBITS(16)
1232 /* read and output the compressed data */
1233 while(n--)
1235 ZIPNEEDBITS(8)
1236 CAB(outbuf)[w++] = (cab_UBYTE)b;
1237 ZIPDUMPBITS(8)
1240 /* restore the globals from the locals */
1241 ZIP(window_posn) = w; /* restore global window pointer */
1242 ZIP(bb) = b; /* restore global bit buffer */
1243 ZIP(bk) = k;
1244 return 0;
1247 /******************************************************
1248 * fdi_Zipinflate_fixed (internal)
1250 static cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1252 struct Ziphuft *fixed_tl;
1253 struct Ziphuft *fixed_td;
1254 cab_LONG fixed_bl, fixed_bd;
1255 cab_LONG i; /* temporary variable */
1256 cab_ULONG *l;
1258 l = ZIP(ll);
1260 /* literal table */
1261 for(i = 0; i < 144; i++)
1262 l[i] = 8;
1263 for(; i < 256; i++)
1264 l[i] = 9;
1265 for(; i < 280; i++)
1266 l[i] = 7;
1267 for(; i < 288; i++) /* make a complete, but wrong code set */
1268 l[i] = 8;
1269 fixed_bl = 7;
1270 if((i = fdi_Ziphuft_build(l, 288, 257, Zipcplens, Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1271 return i;
1273 /* distance table */
1274 for(i = 0; i < 30; i++) /* make an incomplete code set */
1275 l[i] = 5;
1276 fixed_bd = 5;
1277 if((i = fdi_Ziphuft_build(l, 30, 0, Zipcpdist, Zipcpdext, &fixed_td, &fixed_bd, decomp_state)) > 1)
1279 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1280 return i;
1283 /* decompress until an end-of-block code */
1284 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1286 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1287 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1288 return i;
1291 /**************************************************************
1292 * fdi_Zipinflate_dynamic (internal)
1294 static cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1295 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1297 cab_LONG i; /* temporary variables */
1298 cab_ULONG j;
1299 cab_ULONG *ll;
1300 cab_ULONG l; /* last length */
1301 cab_ULONG m; /* mask for bit lengths table */
1302 cab_ULONG n; /* number of lengths to get */
1303 struct Ziphuft *tl; /* literal/length code table */
1304 struct Ziphuft *td; /* distance code table */
1305 cab_LONG bl; /* lookup bits for tl */
1306 cab_LONG bd; /* lookup bits for td */
1307 cab_ULONG nb; /* number of bit length codes */
1308 cab_ULONG nl; /* number of literal/length codes */
1309 cab_ULONG nd; /* number of distance codes */
1310 register cab_ULONG b; /* bit buffer */
1311 register cab_ULONG k; /* number of bits in bit buffer */
1313 /* make local bit buffer */
1314 b = ZIP(bb);
1315 k = ZIP(bk);
1316 ll = ZIP(ll);
1318 /* read in table lengths */
1319 ZIPNEEDBITS(5)
1320 nl = 257 + (b & 0x1f); /* number of literal/length codes */
1321 ZIPDUMPBITS(5)
1322 ZIPNEEDBITS(5)
1323 nd = 1 + (b & 0x1f); /* number of distance codes */
1324 ZIPDUMPBITS(5)
1325 ZIPNEEDBITS(4)
1326 nb = 4 + (b & 0xf); /* number of bit length codes */
1327 ZIPDUMPBITS(4)
1328 if(nl > 288 || nd > 32)
1329 return 1; /* bad lengths */
1331 /* read in bit-length-code lengths */
1332 for(j = 0; j < nb; j++)
1334 ZIPNEEDBITS(3)
1335 ll[Zipborder[j]] = b & 7;
1336 ZIPDUMPBITS(3)
1338 for(; j < 19; j++)
1339 ll[Zipborder[j]] = 0;
1341 /* build decoding table for trees--single level, 7 bit lookup */
1342 bl = 7;
1343 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1345 if(i == 1)
1346 fdi_Ziphuft_free(CAB(hfdi), tl);
1347 return i; /* incomplete code set */
1350 /* read in literal and distance code lengths */
1351 n = nl + nd;
1352 m = Zipmask[bl];
1353 i = l = 0;
1354 while((cab_ULONG)i < n)
1356 ZIPNEEDBITS((cab_ULONG)bl)
1357 j = (td = tl + (b & m))->b;
1358 ZIPDUMPBITS(j)
1359 j = td->v.n;
1360 if (j < 16) /* length of code in bits (0..15) */
1361 ll[i++] = l = j; /* save last length in l */
1362 else if (j == 16) /* repeat last length 3 to 6 times */
1364 ZIPNEEDBITS(2)
1365 j = 3 + (b & 3);
1366 ZIPDUMPBITS(2)
1367 if((cab_ULONG)i + j > n)
1368 return 1;
1369 while (j--)
1370 ll[i++] = l;
1372 else if (j == 17) /* 3 to 10 zero length codes */
1374 ZIPNEEDBITS(3)
1375 j = 3 + (b & 7);
1376 ZIPDUMPBITS(3)
1377 if ((cab_ULONG)i + j > n)
1378 return 1;
1379 while (j--)
1380 ll[i++] = 0;
1381 l = 0;
1383 else /* j == 18: 11 to 138 zero length codes */
1385 ZIPNEEDBITS(7)
1386 j = 11 + (b & 0x7f);
1387 ZIPDUMPBITS(7)
1388 if ((cab_ULONG)i + j > n)
1389 return 1;
1390 while (j--)
1391 ll[i++] = 0;
1392 l = 0;
1396 /* free decoding table for trees */
1397 fdi_Ziphuft_free(CAB(hfdi), tl);
1399 /* restore the global bit buffer */
1400 ZIP(bb) = b;
1401 ZIP(bk) = k;
1403 /* build the decoding tables for literal/length and distance codes */
1404 bl = ZIPLBITS;
1405 if((i = fdi_Ziphuft_build(ll, nl, 257, Zipcplens, Zipcplext, &tl, &bl, decomp_state)) != 0)
1407 if(i == 1)
1408 fdi_Ziphuft_free(CAB(hfdi), tl);
1409 return i; /* incomplete code set */
1411 bd = ZIPDBITS;
1412 fdi_Ziphuft_build(ll + nl, nd, 0, Zipcpdist, Zipcpdext, &td, &bd, decomp_state);
1414 /* decompress until an end-of-block code */
1415 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1416 return 1;
1418 /* free the decoding tables, return */
1419 fdi_Ziphuft_free(CAB(hfdi), tl);
1420 fdi_Ziphuft_free(CAB(hfdi), td);
1421 return 0;
1424 /*****************************************************
1425 * fdi_Zipinflate_block (internal)
1427 static cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1428 { /* decompress an inflated block */
1429 cab_ULONG t; /* block type */
1430 register cab_ULONG b; /* bit buffer */
1431 register cab_ULONG k; /* number of bits in bit buffer */
1433 /* make local bit buffer */
1434 b = ZIP(bb);
1435 k = ZIP(bk);
1437 /* read in last block bit */
1438 ZIPNEEDBITS(1)
1439 *e = (cab_LONG)b & 1;
1440 ZIPDUMPBITS(1)
1442 /* read in block type */
1443 ZIPNEEDBITS(2)
1444 t = b & 3;
1445 ZIPDUMPBITS(2)
1447 /* restore the global bit buffer */
1448 ZIP(bb) = b;
1449 ZIP(bk) = k;
1451 /* inflate that block type */
1452 if(t == 2)
1453 return fdi_Zipinflate_dynamic(decomp_state);
1454 if(t == 0)
1455 return fdi_Zipinflate_stored(decomp_state);
1456 if(t == 1)
1457 return fdi_Zipinflate_fixed(decomp_state);
1458 /* bad block type */
1459 return 2;
1462 /****************************************************
1463 * ZIPfdi_decomp(internal)
1465 static int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1467 cab_LONG e; /* last block flag */
1469 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1471 ZIP(inpos) = CAB(inbuf);
1472 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1473 if(outlen > ZIPWSIZE)
1474 return DECR_DATAFORMAT;
1476 /* CK = Chris Kirmse, official Microsoft purloiner */
1477 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1478 return DECR_ILLEGALDATA;
1479 ZIP(inpos) += 2;
1481 do {
1482 if(fdi_Zipinflate_block(&e, decomp_state))
1483 return DECR_ILLEGALDATA;
1484 } while(!e);
1486 /* return success */
1487 return DECR_OK;
1490 /*******************************************************************
1491 * QTMfdi_decomp(internal)
1493 static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1495 cab_UBYTE *inpos = CAB(inbuf);
1496 cab_UBYTE *window = QTM(window);
1497 cab_UBYTE *runsrc, *rundest;
1498 cab_ULONG window_posn = QTM(window_posn);
1499 cab_ULONG window_size = QTM(window_size);
1501 /* used by bitstream macros */
1502 register int bitsleft, bitrun, bitsneed;
1503 register cab_ULONG bitbuf;
1505 /* used by GET_SYMBOL */
1506 cab_ULONG range;
1507 cab_UWORD symf;
1508 int i;
1510 int extra, togo = outlen, match_length = 0, copy_length;
1511 cab_UBYTE selector, sym;
1512 cab_ULONG match_offset = 0;
1514 cab_UWORD H = 0xFFFF, L = 0, C;
1516 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1518 /* read initial value of C */
1519 Q_INIT_BITSTREAM;
1520 Q_READ_BITS(C, 16);
1522 /* apply 2^x-1 mask */
1523 window_posn &= window_size - 1;
1524 /* runs can't straddle the window wraparound */
1525 if ((window_posn + togo) > window_size) {
1526 TRACE("straddled run\n");
1527 return DECR_DATAFORMAT;
1530 while (togo > 0) {
1531 GET_SYMBOL(model7, selector);
1532 switch (selector) {
1533 case 0:
1534 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1535 break;
1536 case 1:
1537 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1538 break;
1539 case 2:
1540 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1541 break;
1542 case 3:
1543 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1544 break;
1546 case 4:
1547 /* selector 4 = fixed length of 3 */
1548 GET_SYMBOL(model4, sym);
1549 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1550 match_offset = CAB(q_position_base)[sym] + extra + 1;
1551 match_length = 3;
1552 break;
1554 case 5:
1555 /* selector 5 = fixed length of 4 */
1556 GET_SYMBOL(model5, sym);
1557 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1558 match_offset = CAB(q_position_base)[sym] + extra + 1;
1559 match_length = 4;
1560 break;
1562 case 6:
1563 /* selector 6 = variable length */
1564 GET_SYMBOL(model6len, sym);
1565 Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1566 match_length = CAB(q_length_base)[sym] + extra + 5;
1567 GET_SYMBOL(model6pos, sym);
1568 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1569 match_offset = CAB(q_position_base)[sym] + extra + 1;
1570 break;
1572 default:
1573 TRACE("Selector is bogus\n");
1574 return DECR_ILLEGALDATA;
1577 /* if this is a match */
1578 if (selector >= 4) {
1579 rundest = window + window_posn;
1580 togo -= match_length;
1582 /* copy any wrapped around source data */
1583 if (window_posn >= match_offset) {
1584 /* no wrap */
1585 runsrc = rundest - match_offset;
1586 } else {
1587 runsrc = rundest + (window_size - match_offset);
1588 copy_length = match_offset - window_posn;
1589 if (copy_length < match_length) {
1590 match_length -= copy_length;
1591 window_posn += copy_length;
1592 while (copy_length-- > 0) *rundest++ = *runsrc++;
1593 runsrc = window;
1596 window_posn += match_length;
1598 /* copy match data - no worries about destination wraps */
1599 while (match_length-- > 0) *rundest++ = *runsrc++;
1601 } /* while (togo > 0) */
1603 if (togo != 0) {
1604 TRACE("Frame overflow, this_run = %d\n", togo);
1605 return DECR_ILLEGALDATA;
1608 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1609 outlen, outlen);
1611 QTM(window_posn) = window_posn;
1612 return DECR_OK;
1615 /************************************************************
1616 * fdi_lzx_read_lens (internal)
1618 static int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1619 fdi_decomp_state *decomp_state) {
1620 cab_ULONG i,j, x,y;
1621 int z;
1623 register cab_ULONG bitbuf = lb->bb;
1624 register int bitsleft = lb->bl;
1625 cab_UBYTE *inpos = lb->ip;
1626 cab_UWORD *hufftbl;
1628 for (x = 0; x < 20; x++) {
1629 READ_BITS(y, 4);
1630 LENTABLE(PRETREE)[x] = y;
1632 BUILD_TABLE(PRETREE);
1634 for (x = first; x < last; ) {
1635 READ_HUFFSYM(PRETREE, z);
1636 if (z == 17) {
1637 READ_BITS(y, 4); y += 4;
1638 while (y--) lens[x++] = 0;
1640 else if (z == 18) {
1641 READ_BITS(y, 5); y += 20;
1642 while (y--) lens[x++] = 0;
1644 else if (z == 19) {
1645 READ_BITS(y, 1); y += 4;
1646 READ_HUFFSYM(PRETREE, z);
1647 z = lens[x] - z; if (z < 0) z += 17;
1648 while (y--) lens[x++] = z;
1650 else {
1651 z = lens[x] - z; if (z < 0) z += 17;
1652 lens[x++] = z;
1656 lb->bb = bitbuf;
1657 lb->bl = bitsleft;
1658 lb->ip = inpos;
1659 return 0;
1662 /*******************************************************
1663 * LZXfdi_decomp(internal)
1665 static int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1666 cab_UBYTE *inpos = CAB(inbuf);
1667 const cab_UBYTE *endinp = inpos + inlen;
1668 cab_UBYTE *window = LZX(window);
1669 cab_UBYTE *runsrc, *rundest;
1670 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1672 cab_ULONG window_posn = LZX(window_posn);
1673 cab_ULONG window_size = LZX(window_size);
1674 cab_ULONG R0 = LZX(R0);
1675 cab_ULONG R1 = LZX(R1);
1676 cab_ULONG R2 = LZX(R2);
1678 register cab_ULONG bitbuf;
1679 register int bitsleft;
1680 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1681 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1683 int togo = outlen, this_run, main_element, aligned_bits;
1684 int match_length, copy_length, length_footer, extra, verbatim_bits;
1686 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1688 INIT_BITSTREAM;
1690 /* read header if necessary */
1691 if (!LZX(header_read)) {
1692 i = j = 0;
1693 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1694 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1695 LZX(header_read) = 1;
1698 /* main decoding loop */
1699 while (togo > 0) {
1700 /* last block finished, new block expected */
1701 if (LZX(block_remaining) == 0) {
1702 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1703 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1704 INIT_BITSTREAM;
1707 READ_BITS(LZX(block_type), 3);
1708 READ_BITS(i, 16);
1709 READ_BITS(j, 8);
1710 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1712 switch (LZX(block_type)) {
1713 case LZX_BLOCKTYPE_ALIGNED:
1714 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1715 BUILD_TABLE(ALIGNED);
1716 /* rest of aligned header is same as verbatim */
1718 case LZX_BLOCKTYPE_VERBATIM:
1719 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1720 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1721 BUILD_TABLE(MAINTREE);
1722 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1724 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1725 BUILD_TABLE(LENGTH);
1726 break;
1728 case LZX_BLOCKTYPE_UNCOMPRESSED:
1729 LZX(intel_started) = 1; /* because we can't assume otherwise */
1730 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1731 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1732 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1733 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1734 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1735 break;
1737 default:
1738 return DECR_ILLEGALDATA;
1742 /* buffer exhaustion check */
1743 if (inpos > endinp) {
1744 /* it's possible to have a file where the next run is less than
1745 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1746 * in building the tables will exhaust the buffer, so we should
1747 * allow for this, but not allow those accidentally read bits to
1748 * be used (so we check that there are at least 16 bits
1749 * remaining - in this boundary case they aren't really part of
1750 * the compressed data)
1752 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1755 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1756 if (this_run > togo) this_run = togo;
1757 togo -= this_run;
1758 LZX(block_remaining) -= this_run;
1760 /* apply 2^x-1 mask */
1761 window_posn &= window_size - 1;
1762 /* runs can't straddle the window wraparound */
1763 if ((window_posn + this_run) > window_size)
1764 return DECR_DATAFORMAT;
1766 switch (LZX(block_type)) {
1768 case LZX_BLOCKTYPE_VERBATIM:
1769 while (this_run > 0) {
1770 READ_HUFFSYM(MAINTREE, main_element);
1772 if (main_element < LZX_NUM_CHARS) {
1773 /* literal: 0 to LZX_NUM_CHARS-1 */
1774 window[window_posn++] = main_element;
1775 this_run--;
1777 else {
1778 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1779 main_element -= LZX_NUM_CHARS;
1781 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1782 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1783 READ_HUFFSYM(LENGTH, length_footer);
1784 match_length += length_footer;
1786 match_length += LZX_MIN_MATCH;
1788 match_offset = main_element >> 3;
1790 if (match_offset > 2) {
1791 /* not repeated offset */
1792 if (match_offset != 3) {
1793 extra = CAB(extra_bits)[match_offset];
1794 READ_BITS(verbatim_bits, extra);
1795 match_offset = CAB(lzx_position_base)[match_offset]
1796 - 2 + verbatim_bits;
1798 else {
1799 match_offset = 1;
1802 /* update repeated offset LRU queue */
1803 R2 = R1; R1 = R0; R0 = match_offset;
1805 else if (match_offset == 0) {
1806 match_offset = R0;
1808 else if (match_offset == 1) {
1809 match_offset = R1;
1810 R1 = R0; R0 = match_offset;
1812 else /* match_offset == 2 */ {
1813 match_offset = R2;
1814 R2 = R0; R0 = match_offset;
1817 rundest = window + window_posn;
1818 this_run -= match_length;
1820 /* copy any wrapped around source data */
1821 if (window_posn >= match_offset) {
1822 /* no wrap */
1823 runsrc = rundest - match_offset;
1824 } else {
1825 runsrc = rundest + (window_size - match_offset);
1826 copy_length = match_offset - window_posn;
1827 if (copy_length < match_length) {
1828 match_length -= copy_length;
1829 window_posn += copy_length;
1830 while (copy_length-- > 0) *rundest++ = *runsrc++;
1831 runsrc = window;
1834 window_posn += match_length;
1836 /* copy match data - no worries about destination wraps */
1837 while (match_length-- > 0) *rundest++ = *runsrc++;
1840 break;
1842 case LZX_BLOCKTYPE_ALIGNED:
1843 while (this_run > 0) {
1844 READ_HUFFSYM(MAINTREE, main_element);
1846 if (main_element < LZX_NUM_CHARS) {
1847 /* literal: 0 to LZX_NUM_CHARS-1 */
1848 window[window_posn++] = main_element;
1849 this_run--;
1851 else {
1852 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1853 main_element -= LZX_NUM_CHARS;
1855 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1856 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1857 READ_HUFFSYM(LENGTH, length_footer);
1858 match_length += length_footer;
1860 match_length += LZX_MIN_MATCH;
1862 match_offset = main_element >> 3;
1864 if (match_offset > 2) {
1865 /* not repeated offset */
1866 extra = CAB(extra_bits)[match_offset];
1867 match_offset = CAB(lzx_position_base)[match_offset] - 2;
1868 if (extra > 3) {
1869 /* verbatim and aligned bits */
1870 extra -= 3;
1871 READ_BITS(verbatim_bits, extra);
1872 match_offset += (verbatim_bits << 3);
1873 READ_HUFFSYM(ALIGNED, aligned_bits);
1874 match_offset += aligned_bits;
1876 else if (extra == 3) {
1877 /* aligned bits only */
1878 READ_HUFFSYM(ALIGNED, aligned_bits);
1879 match_offset += aligned_bits;
1881 else if (extra > 0) { /* extra==1, extra==2 */
1882 /* verbatim bits only */
1883 READ_BITS(verbatim_bits, extra);
1884 match_offset += verbatim_bits;
1886 else /* extra == 0 */ {
1887 /* ??? */
1888 match_offset = 1;
1891 /* update repeated offset LRU queue */
1892 R2 = R1; R1 = R0; R0 = match_offset;
1894 else if (match_offset == 0) {
1895 match_offset = R0;
1897 else if (match_offset == 1) {
1898 match_offset = R1;
1899 R1 = R0; R0 = match_offset;
1901 else /* match_offset == 2 */ {
1902 match_offset = R2;
1903 R2 = R0; R0 = match_offset;
1906 rundest = window + window_posn;
1907 this_run -= match_length;
1909 /* copy any wrapped around source data */
1910 if (window_posn >= match_offset) {
1911 /* no wrap */
1912 runsrc = rundest - match_offset;
1913 } else {
1914 runsrc = rundest + (window_size - match_offset);
1915 copy_length = match_offset - window_posn;
1916 if (copy_length < match_length) {
1917 match_length -= copy_length;
1918 window_posn += copy_length;
1919 while (copy_length-- > 0) *rundest++ = *runsrc++;
1920 runsrc = window;
1923 window_posn += match_length;
1925 /* copy match data - no worries about destination wraps */
1926 while (match_length-- > 0) *rundest++ = *runsrc++;
1929 break;
1931 case LZX_BLOCKTYPE_UNCOMPRESSED:
1932 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1933 memcpy(window + window_posn, inpos, (size_t) this_run);
1934 inpos += this_run; window_posn += this_run;
1935 break;
1937 default:
1938 return DECR_ILLEGALDATA; /* might as well */
1944 if (togo != 0) return DECR_ILLEGALDATA;
1945 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1946 outlen, (size_t) outlen);
1948 LZX(window_posn) = window_posn;
1949 LZX(R0) = R0;
1950 LZX(R1) = R1;
1951 LZX(R2) = R2;
1953 /* intel E8 decoding */
1954 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1955 if (outlen <= 6 || !LZX(intel_started)) {
1956 LZX(intel_curpos) += outlen;
1958 else {
1959 cab_UBYTE *data = CAB(outbuf);
1960 cab_UBYTE *dataend = data + outlen - 10;
1961 cab_LONG curpos = LZX(intel_curpos);
1962 cab_LONG filesize = LZX(intel_filesize);
1963 cab_LONG abs_off, rel_off;
1965 LZX(intel_curpos) = curpos + outlen;
1967 while (data < dataend) {
1968 if (*data++ != 0xE8) { curpos++; continue; }
1969 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1970 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1971 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1972 data[0] = (cab_UBYTE) rel_off;
1973 data[1] = (cab_UBYTE) (rel_off >> 8);
1974 data[2] = (cab_UBYTE) (rel_off >> 16);
1975 data[3] = (cab_UBYTE) (rel_off >> 24);
1977 data += 4;
1978 curpos += 5;
1982 return DECR_OK;
1985 /**********************************************************
1986 * fdi_decomp (internal)
1988 * Decompress the requested number of bytes. If savemode is zero,
1989 * do not save the output anywhere, just plow through blocks until we
1990 * reach the specified (uncompressed) distance from the starting point,
1991 * and remember the position of the cabfile pointer (and which cabfile)
1992 * after we are done; otherwise, save the data out to CAB(filehf),
1993 * decompressing the requested number of bytes and writing them out. This
1994 * is also where we jump to additional cabinets in the case of split
1995 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1997 static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
1998 char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
2000 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
2001 cab_UBYTE buf[cfdata_SIZEOF], *data;
2002 cab_UWORD inlen, len, outlen, cando;
2003 cab_ULONG cksum;
2004 cab_LONG err;
2005 fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
2007 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
2009 while (bytes > 0) {
2010 /* cando = the max number of bytes we can do */
2011 cando = CAB(outlen);
2012 if (cando > bytes) cando = bytes;
2014 /* if cando != 0 */
2015 if (cando && savemode)
2016 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
2018 CAB(outpos) += cando;
2019 CAB(outlen) -= cando;
2020 bytes -= cando; if (!bytes) break;
2022 /* we only get here if we emptied the output buffer */
2024 /* read data header + data */
2025 inlen = outlen = 0;
2026 while (outlen == 0) {
2027 /* read the block header, skip the reserved part */
2028 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
2029 return DECR_INPUT;
2031 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
2032 return DECR_INPUT;
2034 /* we shouldn't get blocks over CAB_INPUTMAX in size */
2035 data = CAB(inbuf) + inlen;
2036 len = EndGetI16(buf+cfdata_CompressedSize);
2037 inlen += len;
2038 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
2039 if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
2040 return DECR_INPUT;
2042 /* clear two bytes after read-in data */
2043 data[len+1] = data[len+2] = 0;
2045 /* perform checksum test on the block (if one is stored) */
2046 cksum = EndGetI32(buf+cfdata_CheckSum);
2047 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
2048 return DECR_CHECKSUM; /* checksum is wrong */
2050 outlen = EndGetI16(buf+cfdata_UncompressedSize);
2052 /* outlen=0 means this block was the last contiguous part
2053 of a split block, continued in the next cabinet */
2054 if (outlen == 0) {
2055 int pathlen, filenamelen, idx, i;
2056 INT_PTR cabhf;
2057 char fullpath[MAX_PATH], userpath[256];
2058 FDINOTIFICATION fdin;
2059 FDICABINETINFO fdici;
2060 char emptystring = '\0';
2061 cab_UBYTE buf2[64];
2062 int success = FALSE;
2063 struct fdi_folder *fol = NULL, *linkfol = NULL;
2064 struct fdi_file *file = NULL, *linkfile = NULL;
2066 tryanothercab:
2068 /* set up the next decomp_state... */
2069 if (!(cab->next)) {
2070 if (!cab->mii.hasnext) return DECR_INPUT;
2072 if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
2073 return DECR_NOMEMORY;
2075 ZeroMemory(cab->next, sizeof(fdi_decomp_state));
2077 /* copy pszCabPath to userpath */
2078 ZeroMemory(userpath, 256);
2079 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2080 if (pathlen) {
2081 if (pathlen < 256) {
2082 for (i = 0; i <= pathlen; i++)
2083 userpath[i] = pszCabPath[i];
2084 } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2087 /* initial fdintNEXT_CABINET notification */
2088 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2089 fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
2090 fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
2091 fdin.psz3 = &userpath[0];
2092 fdin.fdie = FDIERROR_NONE;
2093 fdin.pv = pvUser;
2095 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2097 do {
2099 pathlen = strlen(userpath);
2100 filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
2102 /* slight overestimation here to save CPU cycles in the developer's brain */
2103 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2104 ERR("MAX_PATH exceeded.\n");
2105 return DECR_ILLEGALDATA;
2108 /* paste the path and filename together */
2109 idx = 0;
2110 if (pathlen) {
2111 for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
2112 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2114 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
2115 fullpath[idx] = '\0';
2117 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2119 /* try to get a handle to the cabfile */
2120 cabhf = PFDI_OPEN(CAB(hfdi), fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2121 if (cabhf == -1) {
2122 /* no file. allow the user to try again */
2123 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2124 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2125 continue;
2128 if (cabhf == 0) {
2129 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2130 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2131 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2132 continue;
2135 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2136 if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
2137 WARN("FDIIsCabinet failed.\n");
2138 PFDI_CLOSE(CAB(hfdi), cabhf);
2139 fdin.fdie = FDIERROR_NOT_A_CABINET;
2140 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2141 continue;
2144 if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
2145 WARN("Wrong Cabinet.\n");
2146 PFDI_CLOSE(CAB(hfdi), cabhf);
2147 fdin.fdie = FDIERROR_WRONG_CABINET;
2148 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2149 continue;
2152 break;
2154 } while (1);
2156 /* cabinet notification */
2157 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2158 fdin.setID = fdici.setID;
2159 fdin.iCabinet = fdici.iCabinet;
2160 fdin.pv = pvUser;
2161 fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2162 fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2163 fdin.psz3 = pszCabPath;
2165 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2167 cab->next->setID = fdici.setID;
2168 cab->next->iCabinet = fdici.iCabinet;
2169 cab->next->hfdi = CAB(hfdi);
2170 cab->next->filehf = CAB(filehf);
2171 cab->next->cabhf = cabhf;
2172 cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2174 cab = cab->next; /* advance to the next cabinet */
2176 /* read folders */
2177 for (i = 0; i < fdici.cFolders; i++) {
2178 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF)
2179 return DECR_INPUT;
2181 if (cab->mii.folder_resv > 0)
2182 PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2184 fol = (struct fdi_folder *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2185 if (!fol) {
2186 ERR("out of memory!\n");
2187 return DECR_NOMEMORY;
2189 ZeroMemory(fol, sizeof(struct fdi_folder));
2190 if (!(cab->firstfol)) cab->firstfol = fol;
2192 fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2193 fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2194 fol->comp_type = EndGetI16(buf2+cffold_CompType);
2196 if (linkfol)
2197 linkfol->next = fol;
2198 linkfol = fol;
2201 /* read files */
2202 for (i = 0; i < fdici.cFiles; i++) {
2203 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2204 return DECR_INPUT;
2206 file = (struct fdi_file *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2207 if (!file) {
2208 ERR("out of memory!\n");
2209 return DECR_NOMEMORY;
2211 ZeroMemory(file, sizeof(struct fdi_file));
2212 if (!(cab->firstfile)) cab->firstfile = file;
2214 file->length = EndGetI32(buf2+cffile_UncompressedSize);
2215 file->offset = EndGetI32(buf2+cffile_FolderOffset);
2216 file->index = EndGetI16(buf2+cffile_FolderIndex);
2217 file->time = EndGetI16(buf2+cffile_Time);
2218 file->date = EndGetI16(buf2+cffile_Date);
2219 file->attribs = EndGetI16(buf2+cffile_Attribs);
2220 file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2222 if (!file->filename) return DECR_INPUT;
2224 if (linkfile)
2225 linkfile->next = file;
2226 linkfile = file;
2229 } else
2230 cab = cab->next; /* advance to the next cabinet */
2232 /* iterate files -- if we encounter the continued file, process it --
2233 otherwise, jump to the label above and keep looking */
2235 for (file = cab->firstfile; (file); file = file->next) {
2236 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2237 /* check to ensure a real match */
2238 if (lstrcmpiA(fi->filename, file->filename) == 0) {
2239 success = TRUE;
2240 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2241 return DECR_INPUT;
2242 break;
2246 if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2247 "Wrong Cabinet" notification? */
2251 /* decompress block */
2252 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2253 return err;
2254 CAB(outlen) = outlen;
2255 CAB(outpos) = CAB(outbuf);
2258 CAB(decomp_cab) = cab;
2259 return DECR_OK;
2262 static void free_decompression_temps(HFDI hfdi, struct fdi_folder *fol,
2263 fdi_decomp_state *decomp_state)
2265 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2266 case cffoldCOMPTYPE_LZX:
2267 if (LZX(window)) {
2268 PFDI_FREE(hfdi, LZX(window));
2269 LZX(window) = NULL;
2271 break;
2272 case cffoldCOMPTYPE_QUANTUM:
2273 if (QTM(window)) {
2274 PFDI_FREE(hfdi, QTM(window));
2275 QTM(window) = NULL;
2277 break;
2281 static void free_decompression_mem(HFDI hfdi, struct fdi_folder *fol,
2282 fdi_decomp_state *decomp_state, fdi_decomp_state *sentinel_decomp_state,
2283 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 if (prev_fds != sentinel_decomp_state)
2310 PFDI_FREE(hfdi, prev_fds);
2314 /***********************************************************************
2315 * FDICopy (CABINET.22)
2317 * Iterates through the files in the Cabinet file indicated by name and
2318 * file-location. May chain forward to additional cabinets (typically
2319 * only one) if files which begin in this Cabinet are continued in another
2320 * cabinet. For each file which is partially contained in this cabinet,
2321 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2322 * notification to the pfnfdin callback. For each file which begins in
2323 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2324 * callback, and the file is optionally decompressed and saved to disk.
2325 * Notification is not provided for files which are not at least partially
2326 * contained in the specified cabinet file.
2328 * See below for a thorough explanation of the various notification
2329 * callbacks.
2331 * PARAMS
2332 * hfdi [I] An HFDI from FDICreate
2333 * pszCabinet [I] C-style string containing the filename of the cabinet
2334 * pszCabPath [I] C-style string containing the file path of the cabinet
2335 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2336 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2337 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2338 * value: NULL.
2339 * pvUser [I] arbitrary void * value which is passed to callbacks.
2341 * RETURNS
2342 * TRUE if successful.
2343 * FALSE if unsuccessful (error information is provided in the ERF structure
2344 * associated with the provided decompression handle by FDICreate).
2346 * CALLBACKS
2348 * Two pointers to callback functions are provided as parameters to FDICopy:
2349 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2350 * types are as follows:
2352 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2353 * PFDINOTIFICATION pfdin );
2355 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2357 * You can create functions of this type using the FNFDINOTIFY() and
2358 * FNFDIDECRYPT() macros, respectively. For example:
2360 * FNFDINOTIFY(mycallback) {
2361 * / * use variables fdint and pfdin to process notification * /
2364 * The second callback, which could be used for decrypting encrypted data,
2365 * is not used at all.
2367 * Each notification informs the user of some event which has occurred during
2368 * decompression of the cabinet file; each notification is also an opportunity
2369 * for the callee to abort decompression. The information provided to the
2370 * callback and the meaning of the callback's return value vary drastically
2371 * across the various types of notification. The type of notification is the
2372 * fdint parameter; all other information is provided to the callback in
2373 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2374 * pfdin. The only part of that structure which is assigned for every callback
2375 * is the pv element, which contains the arbitrary value which was passed to
2376 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2377 * is highly dependent on fdint).
2379 * If you encounter unknown notifications, you should return zero if you want
2380 * decompression to continue (or -1 to abort). All strings used in the
2381 * callbacks are regular C-style strings. Detailed descriptions of each
2382 * notification type follow:
2384 * fdintCABINET_INFO:
2386 * This is the first notification provided after calling FDICopy, and provides
2387 * the user with various information about the cabinet. Note that this is
2388 * called for each cabinet FDICopy opens, not just the first one. In the
2389 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2390 * next cabinet file in the set after the one just loaded (if any), psz2
2391 * contains a pointer to the name or "info" of the next disk, psz3
2392 * contains a pointer to the file-path of the current cabinet, setID
2393 * contains an arbitrary constant associated with this set of cabinet files,
2394 * and iCabinet contains the numerical index of the current cabinet within
2395 * that set. Return zero, or -1 to abort.
2397 * fdintPARTIAL_FILE:
2399 * This notification is provided when FDICopy encounters a part of a file
2400 * contained in this cabinet which is missing its beginning. Files can be
2401 * split across cabinets, so this is not necessarily an abnormality; it just
2402 * means that the file in question begins in another cabinet. No file
2403 * corresponding to this notification is extracted from the cabinet. In the
2404 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2405 * partial file, psz2 contains a pointer to the file name of the cabinet in
2406 * which this file begins, and psz3 contains a pointer to the disk name or
2407 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2409 * fdintCOPY_FILE:
2411 * This notification is provided when FDICopy encounters a file which starts
2412 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2413 * look for files in cabinets after the first one). One notification will be
2414 * sent for each such file, before the file is decompressed. By returning
2415 * zero, the callback can instruct FDICopy to skip the file. In the structure
2416 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2417 * the size of the file (uncompressed), attribs contains the file attributes,
2418 * and date and time contain the date and time of the file. attributes, date,
2419 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2420 * for the entire cabinet, 0 to skip just this file but continue scanning the
2421 * cabinet for more files, or an FDIClose()-compatible file-handle.
2423 * fdintCLOSE_FILE_INFO:
2425 * This notification is important, don't forget to implement it. This
2426 * notification indicates that a file has been successfully uncompressed and
2427 * written to disk. Upon receipt of this notification, the callee is expected
2428 * to close the file handle, to set the attributes and date/time of the
2429 * closed file, and possibly to execute the file. In the structure pointed to
2430 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2431 * open file handle (close it), cb contains 1 or zero, indicating respectively
2432 * that the callee should or should not execute the file, and date, time
2433 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2434 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2435 * do so. Return TRUE, or FALSE to abort decompression.
2437 * fdintNEXT_CABINET:
2439 * This notification is called when FDICopy must load in another cabinet. This
2440 * can occur when a file's data is "split" across multiple cabinets. The
2441 * callee has the opportunity to request that FDICopy look in a different file
2442 * path for the specified cabinet file, by writing that data into a provided
2443 * buffer (see below for more information). This notification will be received
2444 * more than once per-cabinet in the instance that FDICopy failed to find a
2445 * valid cabinet at the location specified by the first per-cabinet
2446 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2447 * structure pointed to by pfdin indicates the error which prevented FDICopy
2448 * from proceeding successfully. Return zero to indicate success, or -1 to
2449 * indicate failure and abort FDICopy.
2451 * Upon receipt of this notification, the structure pointed to by pfdin will
2452 * contain the following values: psz1 pointing to the name of the cabinet
2453 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2454 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2455 * and fdie containing either FDIERROR_NONE, or one of the following:
2457 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2458 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2459 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2460 * FDIERROR_WRONG_CABINET.
2462 * The callee may choose to change the path where FDICopy will look for the
2463 * cabinet after this notification. To do so, the caller may write the new
2464 * pathname to the buffer pointed to by psz3, which is 256 characters in
2465 * length, including the terminating null character, before returning zero.
2467 * fdintENUMERATE:
2469 * Undocumented and unimplemented in wine, this seems to be sent each time
2470 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2471 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2472 * provides information about the current cabinet instead of the next one....
2473 * this is just a guess, it has not been looked at closely.
2475 * INCLUDES
2476 * fdi.c
2478 BOOL __cdecl FDICopy(
2479 HFDI hfdi,
2480 char *pszCabinet,
2481 char *pszCabPath,
2482 int flags,
2483 PFNFDINOTIFY pfnfdin,
2484 PFNFDIDECRYPT pfnfdid,
2485 void *pvUser)
2487 FDICABINETINFO fdici;
2488 FDINOTIFICATION fdin;
2489 INT_PTR cabhf, filehf = 0;
2490 int idx;
2491 unsigned int i;
2492 char fullpath[MAX_PATH];
2493 size_t pathlen, filenamelen;
2494 char emptystring = '\0';
2495 cab_UBYTE buf[64];
2496 struct fdi_folder *fol = NULL, *linkfol = NULL;
2497 struct fdi_file *file = NULL, *linkfile = NULL;
2498 fdi_decomp_state _decomp_state;
2499 fdi_decomp_state *decomp_state = &_decomp_state;
2501 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, "
2502 "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2503 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2505 if (!REALLY_IS_FDI(hfdi)) {
2506 SetLastError(ERROR_INVALID_HANDLE);
2507 return FALSE;
2510 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2512 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2513 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2515 /* slight overestimation here to save CPU cycles in the developer's brain */
2516 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2517 ERR("MAX_PATH exceeded.\n");
2518 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2519 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2520 PFDI_INT(hfdi)->perf->fError = TRUE;
2521 SetLastError(ERROR_FILE_NOT_FOUND);
2522 return FALSE;
2525 /* paste the path and filename together */
2526 idx = 0;
2527 if (pathlen) {
2528 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2529 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2531 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2532 fullpath[idx] = '\0';
2534 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2536 /* get a handle to the cabfile */
2537 cabhf = PFDI_OPEN(hfdi, fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2538 if (cabhf == -1) {
2539 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2540 PFDI_INT(hfdi)->perf->fError = TRUE;
2541 SetLastError(ERROR_FILE_NOT_FOUND);
2542 return FALSE;
2545 if (cabhf == 0) {
2546 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2547 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2548 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2549 PFDI_INT(hfdi)->perf->fError = TRUE;
2550 SetLastError(ERROR_FILE_NOT_FOUND);
2551 return FALSE;
2554 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2555 if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2556 ERR("FDIIsCabinet failed.\n");
2557 PFDI_CLOSE(hfdi, cabhf);
2558 return FALSE;
2561 /* cabinet notification */
2562 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2563 fdin.setID = fdici.setID;
2564 fdin.iCabinet = fdici.iCabinet;
2565 fdin.pv = pvUser;
2566 fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2567 fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2568 fdin.psz3 = pszCabPath;
2570 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2571 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2572 PFDI_INT(hfdi)->perf->erfType = 0;
2573 PFDI_INT(hfdi)->perf->fError = TRUE;
2574 goto bail_and_fail;
2577 CAB(setID) = fdici.setID;
2578 CAB(iCabinet) = fdici.iCabinet;
2579 CAB(cabhf) = cabhf;
2581 /* read folders */
2582 for (i = 0; i < fdici.cFolders; i++) {
2583 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2584 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2585 PFDI_INT(hfdi)->perf->erfType = 0;
2586 PFDI_INT(hfdi)->perf->fError = TRUE;
2587 goto bail_and_fail;
2590 if (CAB(mii).folder_resv > 0)
2591 PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2593 fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2594 if (!fol) {
2595 ERR("out of memory!\n");
2596 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2597 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2598 PFDI_INT(hfdi)->perf->fError = TRUE;
2599 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2600 goto bail_and_fail;
2602 ZeroMemory(fol, sizeof(struct fdi_folder));
2603 if (!CAB(firstfol)) CAB(firstfol) = fol;
2605 fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2606 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2607 fol->comp_type = EndGetI16(buf+cffold_CompType);
2609 if (linkfol)
2610 linkfol->next = fol;
2611 linkfol = fol;
2614 /* read files */
2615 for (i = 0; i < fdici.cFiles; i++) {
2616 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2617 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2618 PFDI_INT(hfdi)->perf->erfType = 0;
2619 PFDI_INT(hfdi)->perf->fError = TRUE;
2620 goto bail_and_fail;
2623 file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2624 if (!file) {
2625 ERR("out of memory!\n");
2626 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2627 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2628 PFDI_INT(hfdi)->perf->fError = TRUE;
2629 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2630 goto bail_and_fail;
2632 ZeroMemory(file, sizeof(struct fdi_file));
2633 if (!CAB(firstfile)) CAB(firstfile) = file;
2635 file->length = EndGetI32(buf+cffile_UncompressedSize);
2636 file->offset = EndGetI32(buf+cffile_FolderOffset);
2637 file->index = EndGetI16(buf+cffile_FolderIndex);
2638 file->time = EndGetI16(buf+cffile_Time);
2639 file->date = EndGetI16(buf+cffile_Date);
2640 file->attribs = EndGetI16(buf+cffile_Attribs);
2641 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2643 if (!file->filename) {
2644 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2645 PFDI_INT(hfdi)->perf->erfType = 0;
2646 PFDI_INT(hfdi)->perf->fError = TRUE;
2647 goto bail_and_fail;
2650 if (linkfile)
2651 linkfile->next = file;
2652 linkfile = file;
2655 for (file = CAB(firstfile); (file); file = file->next) {
2658 * FIXME: This implementation keeps multiple cabinet files open at once
2659 * when encountering a split cabinet. It is a quirk of this implementation
2660 * that sometimes we decrypt the same block of data more than once, to find
2661 * the right starting point for a file, moving the file-pointer backwards.
2662 * If we kept a cache of certain file-pointer information, we could eliminate
2663 * that behavior... in fact I am not sure that the caching we already have
2664 * is not sufficient.
2666 * The current implementation seems to work fine in straightforward situations
2667 * where all the cabinet files needed for decryption are simultaneously
2668 * available. But presumably, the API is supposed to support cabinets which
2669 * are split across multiple CDROMS; we may need to change our implementation
2670 * to strictly serialize it's file usage so that it opens only one cabinet
2671 * at a time. Some experimentation with Windows is needed to figure out the
2672 * precise semantics required. The relevant code is here and in fdi_decomp().
2675 /* partial-file notification */
2676 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2678 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2679 * and perform some tests to figure out the right behavior. The SDK says
2680 * FDICopy will notify the user of the filename and "disk name" (info) of
2681 * the cabinet where the spanning file /started/.
2683 * That would certainly be convenient for the API-user, who could abort,
2684 * everything (or parallelize, if that's allowed (it is in wine)), and call
2685 * FDICopy again with the provided filename, so as to avoid partial file
2686 * notification and successfully unpack. This task could be quite unpleasant
2687 * from wine's perspective: the information specifying the "start cabinet" for
2688 * a file is associated nowhere with the file header and is not to be found in
2689 * the cabinet header. We have only the index of the cabinet wherein the folder
2690 * begins, which contains the file. To find that cabinet, we must consider the
2691 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2692 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2693 * list).
2695 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2696 * cabinet other than the active one might be at another filepath than the
2697 * current one, or on another CDROM. This could get rather dicey, especially
2698 * if we imagine parallelized access to the FDICopy API.
2700 * The current implementation punts -- it just returns the previous cabinet and
2701 * it's info from the header of this cabinet. This provides the right answer in
2702 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2703 * we "fix" it.
2705 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2706 fdin.pv = pvUser;
2707 fdin.psz1 = (char *)file->filename;
2708 fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2709 fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2711 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2712 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2713 PFDI_INT(hfdi)->perf->erfType = 0;
2714 PFDI_INT(hfdi)->perf->fError = TRUE;
2715 goto bail_and_fail;
2717 /* I don't think we are supposed to decompress partial files. This prevents it. */
2718 file->oppressed = TRUE;
2720 if (file->oppressed) {
2721 filehf = 0;
2722 } else {
2723 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2724 fdin.pv = pvUser;
2725 fdin.psz1 = (char *)file->filename;
2726 fdin.cb = file->length;
2727 fdin.date = file->date;
2728 fdin.time = file->time;
2729 fdin.attribs = file->attribs;
2730 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2731 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2732 PFDI_INT(hfdi)->perf->erfType = 0;
2733 PFDI_INT(hfdi)->perf->fError = TRUE;
2734 filehf = 0;
2735 goto bail_and_fail;
2739 /* find the folder for this file if necc. */
2740 if (filehf) {
2741 int i2;
2743 fol = CAB(firstfol);
2744 if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2745 /* pick the last folder */
2746 while (fol->next) fol = fol->next;
2747 } else {
2748 for (i2 = 0; (i2 < file->index); i2++)
2749 if (fol->next) /* bug resistance, should always be true */
2750 fol = fol->next;
2754 if (filehf) {
2755 cab_UWORD comptype = fol->comp_type;
2756 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2757 int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2758 int err = 0;
2760 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2762 /* set up decomp_state */
2763 CAB(hfdi) = hfdi;
2764 CAB(filehf) = filehf;
2766 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2767 if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2769 TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2771 /* free stuff for the old decompresser */
2772 switch (ct2) {
2773 case cffoldCOMPTYPE_LZX:
2774 if (LZX(window)) {
2775 PFDI_FREE(hfdi, LZX(window));
2776 LZX(window) = NULL;
2778 break;
2779 case cffoldCOMPTYPE_QUANTUM:
2780 if (QTM(window)) {
2781 PFDI_FREE(hfdi, QTM(window));
2782 QTM(window) = NULL;
2784 break;
2787 CAB(decomp_cab) = NULL;
2788 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2789 CAB(offset) = 0;
2790 CAB(outlen) = 0;
2792 /* initialize the new decompresser */
2793 switch (ct1) {
2794 case cffoldCOMPTYPE_NONE:
2795 CAB(decompress) = NONEfdi_decomp;
2796 break;
2797 case cffoldCOMPTYPE_MSZIP:
2798 CAB(decompress) = ZIPfdi_decomp;
2799 break;
2800 case cffoldCOMPTYPE_QUANTUM:
2801 CAB(decompress) = QTMfdi_decomp;
2802 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2803 break;
2804 case cffoldCOMPTYPE_LZX:
2805 CAB(decompress) = LZXfdi_decomp;
2806 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2807 break;
2808 default:
2809 err = DECR_DATAFORMAT;
2813 CAB(current) = fol;
2815 switch (err) {
2816 case DECR_OK:
2817 break;
2818 case DECR_NOMEMORY:
2819 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2820 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2821 PFDI_INT(hfdi)->perf->fError = TRUE;
2822 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2823 goto bail_and_fail;
2824 default:
2825 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2826 PFDI_INT(hfdi)->perf->erfOper = 0;
2827 PFDI_INT(hfdi)->perf->fError = TRUE;
2828 goto bail_and_fail;
2831 if (file->offset > CAB(offset)) {
2832 /* decode bytes and send them to /dev/null */
2833 switch (fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser)) {
2834 case DECR_OK:
2835 break;
2836 case DECR_USERABORT:
2837 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2838 PFDI_INT(hfdi)->perf->erfType = 0;
2839 PFDI_INT(hfdi)->perf->fError = TRUE;
2840 goto bail_and_fail;
2841 case DECR_NOMEMORY:
2842 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2843 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2844 PFDI_INT(hfdi)->perf->fError = TRUE;
2845 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2846 goto bail_and_fail;
2847 default:
2848 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2849 PFDI_INT(hfdi)->perf->erfOper = 0;
2850 PFDI_INT(hfdi)->perf->fError = TRUE;
2851 goto bail_and_fail;
2853 CAB(offset) = file->offset;
2856 /* now do the actual decompression */
2857 err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2858 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2860 /* fdintCLOSE_FILE_INFO notification */
2861 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2862 fdin.pv = pvUser;
2863 fdin.psz1 = (char *)file->filename;
2864 fdin.hf = filehf;
2865 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2866 fdin.date = file->date;
2867 fdin.time = file->time;
2868 fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2869 ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2870 filehf = 0;
2872 switch (err) {
2873 case DECR_OK:
2874 break;
2875 case DECR_USERABORT:
2876 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2877 PFDI_INT(hfdi)->perf->erfType = 0;
2878 PFDI_INT(hfdi)->perf->fError = TRUE;
2879 goto bail_and_fail;
2880 case DECR_NOMEMORY:
2881 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2882 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2883 PFDI_INT(hfdi)->perf->fError = TRUE;
2884 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2885 goto bail_and_fail;
2886 default:
2887 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2888 PFDI_INT(hfdi)->perf->erfOper = 0;
2889 PFDI_INT(hfdi)->perf->fError = TRUE;
2890 goto bail_and_fail;
2895 free_decompression_temps(hfdi, fol, decomp_state);
2896 free_decompression_mem(hfdi, fol, decomp_state, &_decomp_state, file);
2898 return TRUE;
2900 bail_and_fail: /* here we free ram before error returns */
2902 free_decompression_temps(hfdi, fol, decomp_state);
2904 if (filehf) PFDI_CLOSE(hfdi, filehf);
2906 free_decompression_mem(hfdi, fol, decomp_state, &_decomp_state, file);
2908 return FALSE;
2911 /***********************************************************************
2912 * FDIDestroy (CABINET.23)
2914 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2915 * of FDICopy. Only reason for failure would be an invalid handle.
2917 * PARAMS
2918 * hfdi [I] The HFDI to free
2920 * RETURNS
2921 * TRUE for success
2922 * FALSE for failure
2924 BOOL __cdecl FDIDestroy(HFDI hfdi)
2926 TRACE("(hfdi == ^%p)\n", hfdi);
2927 if (REALLY_IS_FDI(hfdi)) {
2928 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2929 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2930 return TRUE;
2931 } else {
2932 SetLastError(ERROR_INVALID_HANDLE);
2933 return FALSE;
2937 /***********************************************************************
2938 * FDITruncateCabinet (CABINET.24)
2940 * Removes all folders of a cabinet file after and including the
2941 * specified folder number.
2943 * PARAMS
2944 * hfdi [I] Handle to the FDI context.
2945 * pszCabinetName [I] Filename of the cabinet.
2946 * iFolderToDelete [I] Index of the first folder to delete.
2948 * RETURNS
2949 * Success: TRUE.
2950 * Failure: FALSE.
2952 * NOTES
2953 * The PFNWRITE function supplied to FDICreate must truncate the
2954 * file at the current position if the number of bytes to write is 0.
2956 BOOL __cdecl FDITruncateCabinet(
2957 HFDI hfdi,
2958 char *pszCabinetName,
2959 USHORT iFolderToDelete)
2961 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2962 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2964 if (!REALLY_IS_FDI(hfdi)) {
2965 SetLastError(ERROR_INVALID_HANDLE);
2966 return FALSE;
2969 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2970 return FALSE;