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
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?
46 * Probably, I need to weed out some dead code-paths.
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.
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
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 */
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
106 char *prevname, *previnfo;
107 char *nextname, *nextinfo;
108 BOOL hasnext; /* bug free indicator */
109 int folder_resv, header_resv;
110 cab_UBYTE block_resv;
111 } MORE_ISCAB_INFO, *PMORE_ISCAB_INFO;
114 * ugh, well, this ended up being pretty damn silly...
115 * now that I've conceded to build equivalent structures to struct cab.*,
116 * I should have just used those, or, better yet, unified the two... sue me.
117 * (Note to Microsoft: That's a joke. Please /don't/ actually sue me! -gmt).
118 * Nevertheless, I've come this far, it works, so I'm not gonna change it
119 * for now. This implementation has significant semantic differences anyhow.
122 typedef struct fdi_cds_fwd {
123 void *hfdi; /* the hfdi we are using */
124 int filehf, cabhf; /* file handle we are using */
125 struct fdi_folder *current; /* current folder we're extracting from */
126 cab_ULONG offset; /* uncompressed offset within folder */
127 cab_UBYTE *outpos; /* (high level) start of data to use up */
128 cab_UWORD outlen; /* (high level) amount of data to use up */
129 int (*decompress)(int, int, struct fdi_cds_fwd *); /* chosen compress fn */
130 cab_UBYTE inbuf[CAB_INPUTMAX+2]; /* +2 for lzx bitbuffer overflows! */
131 cab_UBYTE outbuf[CAB_BLOCKMAX];
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;
146 struct fdi_folder *firstfol;
147 struct fdi_file *firstfile;
148 struct fdi_cds_fwd *next;
151 /****************************************************************
152 * QTMupdatemodel (internal)
154 void QTMupdatemodel(struct QTMmodel *model, int sym) {
155 struct QTMmodelsym temp;
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;
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
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.
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.
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;
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) {
239 if((pos += bit_mask) > table_mask) return 1; /* table overrun */
241 /* fill all possible lookups of this symbol with the symbol itself */
243 while (fill-- > 0) table[leaf++] = sym;
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 */
260 while (bit_num <= 16) {
261 for (sym = 0; sym < nsyms; sym++) {
262 if (length[sym] == bit_num) {
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++;
277 if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
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;
293 /*************************************************************************
294 * checksum (internal)
296 cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum) {
300 for (len = bytes >> 2; len--; data += 4) {
301 csum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
305 case 3: ul |= *data++ << 16;
306 case 2: ul |= *data++ << 8;
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
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
331 * pfnwrite [I] A pointer to a function which writes to a file from
332 * a caller-provided buffer. Uses the same interface
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.
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.
353 HFDI __cdecl FDICreate(
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,
371 if ((!pfnalloc) || (!pfnfree)) {
372 perf->erfOper = FDIERROR_NONE;
373 perf->erfType = ERROR_BAD_ARGUMENTS;
376 SetLastError(ERROR_BAD_ARGUMENTS);
380 if (!((rv = ((HFDI) (*pfnalloc)(sizeof(FDI_Int)))))) {
381 perf->erfOper = FDIERROR_ALLOC_FAIL;
382 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
385 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
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;
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_realloc (internal)
417 * we can't use _msize; the user might not be using malloc, so we require
418 * an explicit specification of the previous size. inefficient.
420 static void *FDI_realloc(HFDI hfdi, void *mem, size_t prevsize, size_t newsize)
424 size_t copysize = (prevsize < newsize) ? prevsize : newsize;
425 if (prevsize == newsize) return mem;
426 rslt = PFDI_ALLOC(hfdi, newsize);
428 for (irslt = (char *)rslt, imem = (char *)mem; (copysize); copysize--)
430 PFDI_FREE(hfdi, mem);
434 /**********************************************************************
435 * FDI_read_string (internal)
437 * allocate and read an arbitrarily long string from the cabinet
439 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
443 base = FDI_getoffset(hfdi, hf),
444 maxlen = cabsize - base;
447 cab_UBYTE *buf = NULL;
449 TRACE("(hfdi == ^%p, hf == %d)\n", hfdi, hf);
452 if (len > maxlen) len = maxlen;
453 if (!(buf = FDI_realloc(hfdi, buf, oldlen, len))) break;
455 if (!PFDI_READ(hfdi, hf, buf, len)) break;
457 /* search for a null terminator in what we've just read */
458 for (i=0; i < len; i++) {
459 if (!buf[i]) {ok=TRUE; break;}
464 ERR("cabinet is truncated\n");
468 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
474 PFDI_FREE(hfdi, buf);
476 ERR("out of memory!\n");
480 /* otherwise, set the stream to just after the string and return */
481 PFDI_SEEK(hfdi, hf, base + ((cab_off_t) strlen((char *) buf)) + 1, SEEK_SET);
486 /******************************************************************
487 * FDI_read_entries (internal)
489 * process the cabinet header in the style of FDIIsCabinet, but
490 * without the sanity checks (and bug)
492 static BOOL FDI_read_entries(
495 PFDICABINETINFO pfdici,
496 PMORE_ISCAB_INFO pmii)
498 int num_folders, num_files, header_resv, folder_resv = 0;
499 LONG base_offset, cabsize;
500 USHORT setid, cabidx, flags;
501 cab_UBYTE buf[64], block_resv;
502 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
504 TRACE("(hfdi == ^%p, hf == %d, pfdici == ^%p)\n", hfdi, hf, pfdici);
507 * FIXME: I just noticed that I am memorizing the initial file pointer
508 * offset and restoring it before reading in the rest of the header
509 * information in the cabinet. Perhaps that's correct -- that is, perhaps
510 * this API is supposed to support "streaming" cabinets which are embedded
511 * in other files, or cabinets which begin at file offsets other than zero.
512 * Otherwise, I should instead go to the absolute beginning of the file.
513 * (Either way, the semantics of wine's FDICopy require me to leave the
514 * file pointer where it is afterwards -- If Windows does not do so, we
515 * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
517 * So, the answer lies in Windows; will native cabinet.dll recognize a
518 * cabinet "file" embedded in another file? Note that cabextract.c does
519 * support this, which implies that Microsoft's might. I haven't tried it
520 * yet so I don't know. ATM, most of wine's FDI cabinet routines (except
521 * this one) would not work in this way. To fix it, we could just make the
522 * various references to absolute file positions in the code relative to an
523 * initial "beginning" offset. Because the FDICopy API doesn't take a
524 * file-handle like this one, we would therein need to search through the
525 * file for the beginning of the cabinet (as we also do in cabextract.c).
526 * Note that this limits us to a maximum of one cabinet per. file: the first.
528 * So, in summary: either the code below is wrong, or the rest of fdi.c is
529 * wrong... I cannot imagine that both are correct ;) One of these flaws
530 * should be fixed after determining the behavior on Windows. We ought
531 * to check both FDIIsCabinet and FDICopy for the right behavior.
536 /* get basic offset & size info */
537 base_offset = FDI_getoffset(hfdi, hf);
539 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
541 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
542 PFDI_INT(hfdi)->perf->erfType = 0;
543 PFDI_INT(hfdi)->perf->fError = TRUE;
548 cabsize = FDI_getoffset(hfdi, hf);
550 if ((cabsize == -1) || (base_offset == -1) ||
551 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
553 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
554 PFDI_INT(hfdi)->perf->erfType = 0;
555 PFDI_INT(hfdi)->perf->fError = TRUE;
560 /* read in the CFHEADER */
561 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
563 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
564 PFDI_INT(hfdi)->perf->erfType = 0;
565 PFDI_INT(hfdi)->perf->fError = TRUE;
570 /* check basic MSCF signature */
571 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
573 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
574 PFDI_INT(hfdi)->perf->erfType = 0;
575 PFDI_INT(hfdi)->perf->fError = TRUE;
580 /* get the number of folders */
581 num_folders = EndGetI16(buf+cfhead_NumFolders);
582 if (num_folders == 0) {
583 /* PONDERME: is this really invalid? */
584 WARN("weird cabinet detect failure: no folders in cabinet\n");
586 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
587 PFDI_INT(hfdi)->perf->erfType = 0;
588 PFDI_INT(hfdi)->perf->fError = TRUE;
593 /* get the number of files */
594 num_files = EndGetI16(buf+cfhead_NumFiles);
595 if (num_files == 0) {
596 /* PONDERME: is this really invalid? */
597 WARN("weird cabinet detect failure: no files in cabinet\n");
599 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
600 PFDI_INT(hfdi)->perf->erfType = 0;
601 PFDI_INT(hfdi)->perf->fError = TRUE;
607 setid = EndGetI16(buf+cfhead_SetID);
609 /* cabinet (set) index */
610 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
612 /* check the header revision */
613 if ((buf[cfhead_MajorVersion] > 1) ||
614 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
616 WARN("cabinet format version > 1.3\n");
618 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
619 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
620 PFDI_INT(hfdi)->perf->fError = TRUE;
625 /* pull the flags out */
626 flags = EndGetI16(buf+cfhead_Flags);
628 /* read the reserved-sizes part of header, if present */
629 if (flags & cfheadRESERVE_PRESENT) {
630 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
631 ERR("bunk reserve-sizes?\n");
633 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
634 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
635 PFDI_INT(hfdi)->perf->fError = TRUE;
640 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
641 if (pmii) pmii->header_resv = header_resv;
642 folder_resv = buf[cfheadext_FolderReserved];
643 if (pmii) pmii->folder_resv = folder_resv;
644 block_resv = buf[cfheadext_DataReserved];
645 if (pmii) pmii->block_resv = block_resv;
647 if (header_resv > 60000) {
648 WARN("WARNING; header reserved space > 60000\n");
651 /* skip the reserved header */
652 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
653 ERR("seek failure: header_resv\n");
655 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
656 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
657 PFDI_INT(hfdi)->perf->fError = TRUE;
663 if (flags & cfheadPREV_CABINET) {
664 prevname = FDI_read_string(hfdi, hf, cabsize);
667 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
668 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
669 PFDI_INT(hfdi)->perf->fError = TRUE;
674 pmii->prevname = prevname;
676 PFDI_FREE(hfdi, prevname);
677 previnfo = FDI_read_string(hfdi, hf, cabsize);
680 pmii->previnfo = previnfo;
682 PFDI_FREE(hfdi, previnfo);
686 if (flags & cfheadNEXT_CABINET) {
688 pmii->hasnext = TRUE;
689 nextname = FDI_read_string(hfdi, hf, cabsize);
691 if ((flags & cfheadPREV_CABINET) && pmii) {
692 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
693 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
695 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
696 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
697 PFDI_INT(hfdi)->perf->fError = TRUE;
701 pmii->nextname = nextname;
703 PFDI_FREE(hfdi, nextname);
704 nextinfo = FDI_read_string(hfdi, hf, cabsize);
707 pmii->nextinfo = nextinfo;
709 PFDI_FREE(hfdi, nextinfo);
713 /* we could process the whole cabinet searching for problems;
714 instead lets stop here. Now let's fill out the paperwork */
715 pfdici->cbCabinet = cabsize;
716 pfdici->cFolders = num_folders;
717 pfdici->cFiles = num_files;
718 pfdici->setID = setid;
719 pfdici->iCabinet = cabidx;
720 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
721 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
722 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
726 /***********************************************************************
727 * FDIIsCabinet (CABINET.21)
729 * Informs the caller as to whether or not the provided file handle is
730 * really a cabinet or not, filling out the provided PFDICABINETINFO
731 * structure with information about the cabinet. Brief explanations of
732 * the elements of this structure are available as comments accompanying
733 * its definition in wine's include/fdi.h.
736 * hfdi [I] An HFDI from FDICreate
737 * hf [I] The file handle about which the caller inquires
738 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
739 * be filled out with information about the cabinet
740 * file indicated by hf if, indeed, it is determined
744 * TRUE if the file is a cabinet. The info pointed to by pfdici will
746 * FALSE if the file is not a cabinet, or if an error was encountered
747 * while processing the cabinet. The PERF structure provided to
748 * FDICreate can be queried for more error information.
753 BOOL __cdecl FDIIsCabinet(
756 PFDICABINETINFO pfdici)
760 TRACE("(hfdi == ^%p, hf == ^%d, pfdici == ^%p)\n", hfdi, hf, pfdici);
762 if (!REALLY_IS_FDI(hfdi)) {
763 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
764 SetLastError(ERROR_INVALID_HANDLE);
770 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
771 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
772 PFDI_INT(hfdi)->perf->fError = TRUE; */
773 SetLastError(ERROR_INVALID_HANDLE);
779 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
780 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
781 PFDI_INT(hfdi)->perf->fError = TRUE; */
782 SetLastError(ERROR_BAD_ARGUMENTS);
785 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
788 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
793 /******************************************************************
794 * QTMfdi_initmodel (internal)
796 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
798 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
803 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
804 for (i = 0; i < n; i++) {
805 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
806 m->syms[i].sym = i+s; /* actual symbol */
807 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
809 m->syms[n].cumfreq = 0;
812 /******************************************************************
813 * QTMfdi_init (internal)
815 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
816 unsigned int wndsize = 1 << window;
817 int msz = window * 2, i;
820 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
821 /* if a previously allocated window is big enough, keep it */
822 if (window < 10 || window > 21) return DECR_DATAFORMAT;
823 if (QTM(actual_size) < wndsize) {
824 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
828 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
829 QTM(actual_size) = wndsize;
831 QTM(window_size) = wndsize;
832 QTM(window_posn) = 0;
834 /* initialize static slot/extrabits tables */
835 for (i = 0, j = 0; i < 27; i++) {
836 CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
837 CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
839 for (i = 0, j = 0; i < 42; i++) {
840 CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
841 CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
844 /* initialize arithmetic coding models */
846 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
848 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
849 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
850 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
851 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
853 /* model 4 depends on table size, ranges from 20 to 24 */
854 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
855 /* model 5 depends on table size, ranges from 20 to 36 */
856 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
857 /* model 6pos depends on table size, ranges from 20 to 42 */
858 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
859 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
864 /************************************************************
865 * LZXfdi_init (internal)
867 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
868 static const cab_UBYTE bits[] =
869 { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
870 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
871 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
873 static const cab_ULONG base[] =
874 { 0, 1, 2, 3, 4, 6, 8, 12,
875 16, 24, 32, 48, 64, 96, 128, 192,
876 256, 384, 512, 768, 1024, 1536, 2048, 3072,
877 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
878 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
879 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
880 1835008, 1966080, 2097152};
881 cab_ULONG wndsize = 1 << window;
884 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
885 /* if a previously allocated window is big enough, keep it */
886 if (window < 15 || window > 21) return DECR_DATAFORMAT;
887 if (LZX(actual_size) < wndsize) {
888 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
892 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
893 LZX(actual_size) = wndsize;
895 LZX(window_size) = wndsize;
897 /* initialize static tables */
898 memcpy(CAB(extra_bits), bits, sizeof(bits));
899 memcpy(CAB(lzx_position_base), base, sizeof(base));
901 /* calculate required position slots */
902 if (window == 20) posn_slots = 42;
903 else if (window == 21) posn_slots = 50;
904 else posn_slots = window << 1;
906 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
908 LZX(R0) = LZX(R1) = LZX(R2) = 1;
909 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
910 LZX(header_read) = 0;
911 LZX(frames_read) = 0;
912 LZX(block_remaining) = 0;
913 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
914 LZX(intel_curpos) = 0;
915 LZX(intel_started) = 0;
916 LZX(window_posn) = 0;
918 /* initialize tables to 0 (because deltas will be applied to them) */
919 memset(LZX(MAINTREE_len), 0, sizeof(LZX(MAINTREE_len)));
920 memset(LZX(LENGTH_len), 0, sizeof(LZX(LENGTH_len)));
925 /****************************************************
926 * NONEfdi_decomp(internal)
928 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
930 if (inlen != outlen) return DECR_ILLEGALDATA;
931 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
935 /********************************************************
936 * Ziphuft_free (internal)
938 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
940 register struct Ziphuft *p, *q;
942 /* Go through linked list, freeing from the allocated (t[-1]) address. */
944 while (p != (struct Ziphuft *)NULL)
952 /*********************************************************
953 * fdi_Ziphuft_build (internal)
955 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, const cab_UWORD *d, const cab_UWORD *e,
956 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
958 cab_ULONG a; /* counter for codes of length k */
959 cab_ULONG el; /* length of EOB code (value 256) */
960 cab_ULONG f; /* i repeats in table every f entries */
961 cab_LONG g; /* maximum code length */
962 cab_LONG h; /* table level */
963 register cab_ULONG i; /* counter, current code */
964 register cab_ULONG j; /* counter */
965 register cab_LONG k; /* number of bits in current code */
966 cab_LONG *l; /* stack of bits per table */
967 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
968 register struct Ziphuft *q; /* points to current table */
969 struct Ziphuft r; /* table entry for structure assignment */
970 register cab_LONG w; /* bits before this table == (l * h) */
971 cab_ULONG *xp; /* pointer into x */
972 cab_LONG y; /* number of dummy codes added */
973 cab_ULONG z; /* number of entries in current table */
977 /* Generate counts for each bit length */
978 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
980 for(i = 0; i < ZIPBMAX+1; ++i)
985 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
987 if (ZIP(c)[0] == n) /* null input--all zero length codes */
989 *t = (struct Ziphuft *)NULL;
994 /* Find minimum and maximum length, bound *m by those */
995 for (j = 1; j <= ZIPBMAX; j++)
998 k = j; /* minimum code length */
999 if ((cab_ULONG)*m < j)
1001 for (i = ZIPBMAX; i; i--)
1004 g = i; /* maximum code length */
1005 if ((cab_ULONG)*m > i)
1008 /* Adjust last length count to fill out codes, if needed */
1009 for (y = 1 << j; j < i; j++, y <<= 1)
1010 if ((y -= ZIP(c)[j]) < 0)
1011 return 2; /* bad input: more codes than bits */
1012 if ((y -= ZIP(c)[i]) < 0)
1016 /* Generate starting offsets LONGo the value table for each length */
1018 p = ZIP(c) + 1; xp = ZIP(x) + 2;
1020 { /* note that i == g from above */
1021 *xp++ = (j += *p++);
1024 /* Make a table of values in order of bit lengths */
1027 if ((j = *p++) != 0)
1028 ZIP(v)[ZIP(x)[j]++] = i;
1032 /* Generate the Huffman codes and for each, make the table entries */
1033 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
1034 p = ZIP(v); /* grab values in bit order */
1035 h = -1; /* no tables yet--level -1 */
1036 w = l[-1] = 0; /* no bits decoded yet */
1037 ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */
1038 q = (struct Ziphuft *)NULL; /* ditto */
1041 /* go through the bit lengths (k already is bits in shortest code) */
1047 /* here i is the Huffman code of length k bits for value *p */
1048 /* make tables up to required level */
1049 while (k > w + l[h])
1051 w += l[h++]; /* add bits already decoded */
1053 /* compute minimum size table less than or equal to *m bits */
1054 z = (z = g - w) > (cab_ULONG)*m ? *m : z; /* upper limit */
1055 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
1056 { /* too few codes for k-w bit table */
1057 f -= a + 1; /* deduct codes from patterns left */
1059 while (++j < z) /* try smaller tables up to z bits */
1061 if ((f <<= 1) <= *++xp)
1062 break; /* enough codes to use up j bits */
1063 f -= *xp; /* else deduct codes from patterns */
1066 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
1067 j = el - w; /* make EOB code end at table */
1068 z = 1 << j; /* table entries for j-bit table */
1069 l[h] = j; /* set table size in stack */
1071 /* allocate and link in new table */
1072 if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
1075 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
1076 return 3; /* not enough memory */
1078 *t = q + 1; /* link to list for Ziphuft_free() */
1079 *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
1080 ZIP(u)[h] = ++q; /* table starts after link */
1082 /* connect to last table, if there is one */
1085 ZIP(x)[h] = i; /* save pattern for backing up */
1086 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
1087 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
1088 r.v.t = q; /* pointer to this table */
1089 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
1090 ZIP(u)[h-1][j] = r; /* connect to last table */
1094 /* set up table entry in r */
1095 r.b = (cab_UBYTE)(k - w);
1096 if (p >= ZIP(v) + n)
1097 r.e = 99; /* out of values--invalid code */
1100 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
1101 r.v.n = *p++; /* simple code is just the value */
1105 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
1106 r.v.n = d[*p++ - s];
1109 /* fill code-like entries with r */
1111 for (j = i >> w; j < z; j += f)
1114 /* backwards increment the k-bit code i */
1115 for (j = 1 << (k - 1); i & j; j >>= 1)
1119 /* backup over finished tables */
1120 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
1121 w -= l[--h]; /* don't need to update q */
1125 /* return actual size of base table */
1128 /* Return true (1) if we were given an incomplete table */
1129 return y != 0 && g != 1;
1132 /*********************************************************
1133 * fdi_Zipinflate_codes (internal)
1135 static cab_LONG fdi_Zipinflate_codes(const struct Ziphuft *tl, const struct Ziphuft *td,
1136 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
1138 register cab_ULONG e; /* table entry flag/number of extra bits */
1139 cab_ULONG n, d; /* length and index for copy */
1140 cab_ULONG w; /* current window position */
1141 const struct Ziphuft *t; /* pointer to table entry */
1142 cab_ULONG ml, md; /* masks for bl and bd bits */
1143 register cab_ULONG b; /* bit buffer */
1144 register cab_ULONG k; /* number of bits in bit buffer */
1146 /* make local copies of globals */
1147 b = ZIP(bb); /* initialize bit buffer */
1149 w = ZIP(window_posn); /* initialize window position */
1151 /* inflate the coded data */
1152 ml = Zipmask[bl]; /* precompute masks for speed */
1157 ZIPNEEDBITS((cab_ULONG)bl)
1158 if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16)
1166 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
1168 if (e == 16) /* then it's a literal */
1169 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
1170 else /* it's an EOB or a length */
1172 /* exit if end of block */
1176 /* get length of block to copy */
1178 n = t->v.n + ((cab_ULONG)b & Zipmask[e]);
1181 /* decode distance of block to copy */
1182 ZIPNEEDBITS((cab_ULONG)bd)
1183 if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16)
1190 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
1193 d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]);
1197 n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
1200 CAB(outbuf)[w++] = CAB(outbuf)[d++];
1206 /* restore the globals from the locals */
1207 ZIP(window_posn) = w; /* restore global window pointer */
1208 ZIP(bb) = b; /* restore global bit buffer */
1215 /***********************************************************
1216 * Zipinflate_stored (internal)
1218 static cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1219 /* "decompress" an inflated type 0 (stored) block. */
1221 cab_ULONG n; /* number of bytes in block */
1222 cab_ULONG w; /* current window position */
1223 register cab_ULONG b; /* bit buffer */
1224 register cab_ULONG k; /* number of bits in bit buffer */
1226 /* make local copies of globals */
1227 b = ZIP(bb); /* initialize bit buffer */
1229 w = ZIP(window_posn); /* initialize window position */
1231 /* go to byte boundary */
1235 /* get the length and its complement */
1237 n = ((cab_ULONG)b & 0xffff);
1240 if (n != (cab_ULONG)((~b) & 0xffff))
1241 return 1; /* error in compressed data */
1244 /* read and output the compressed data */
1248 CAB(outbuf)[w++] = (cab_UBYTE)b;
1252 /* restore the globals from the locals */
1253 ZIP(window_posn) = w; /* restore global window pointer */
1254 ZIP(bb) = b; /* restore global bit buffer */
1259 /******************************************************
1260 * fdi_Zipinflate_fixed (internal)
1262 static cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1264 struct Ziphuft *fixed_tl;
1265 struct Ziphuft *fixed_td;
1266 cab_LONG fixed_bl, fixed_bd;
1267 cab_LONG i; /* temporary variable */
1273 for(i = 0; i < 144; i++)
1279 for(; i < 288; i++) /* make a complete, but wrong code set */
1282 if((i = fdi_Ziphuft_build(l, 288, 257, Zipcplens, Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1285 /* distance table */
1286 for(i = 0; i < 30; i++) /* make an incomplete code set */
1289 if((i = fdi_Ziphuft_build(l, 30, 0, Zipcpdist, Zipcpdext, &fixed_td, &fixed_bd, decomp_state)) > 1)
1291 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1295 /* decompress until an end-of-block code */
1296 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1298 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1299 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1303 /**************************************************************
1304 * fdi_Zipinflate_dynamic (internal)
1306 static cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1307 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1309 cab_LONG i; /* temporary variables */
1312 cab_ULONG l; /* last length */
1313 cab_ULONG m; /* mask for bit lengths table */
1314 cab_ULONG n; /* number of lengths to get */
1315 struct Ziphuft *tl; /* literal/length code table */
1316 struct Ziphuft *td; /* distance code table */
1317 cab_LONG bl; /* lookup bits for tl */
1318 cab_LONG bd; /* lookup bits for td */
1319 cab_ULONG nb; /* number of bit length codes */
1320 cab_ULONG nl; /* number of literal/length codes */
1321 cab_ULONG nd; /* number of distance codes */
1322 register cab_ULONG b; /* bit buffer */
1323 register cab_ULONG k; /* number of bits in bit buffer */
1325 /* make local bit buffer */
1330 /* read in table lengths */
1332 nl = 257 + ((cab_ULONG)b & 0x1f); /* number of literal/length codes */
1335 nd = 1 + ((cab_ULONG)b & 0x1f); /* number of distance codes */
1338 nb = 4 + ((cab_ULONG)b & 0xf); /* number of bit length codes */
1340 if(nl > 288 || nd > 32)
1341 return 1; /* bad lengths */
1343 /* read in bit-length-code lengths */
1344 for(j = 0; j < nb; j++)
1347 ll[Zipborder[j]] = (cab_ULONG)b & 7;
1351 ll[Zipborder[j]] = 0;
1353 /* build decoding table for trees--single level, 7 bit lookup */
1355 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1358 fdi_Ziphuft_free(CAB(hfdi), tl);
1359 return i; /* incomplete code set */
1362 /* read in literal and distance code lengths */
1366 while((cab_ULONG)i < n)
1368 ZIPNEEDBITS((cab_ULONG)bl)
1369 j = (td = tl + ((cab_ULONG)b & m))->b;
1372 if (j < 16) /* length of code in bits (0..15) */
1373 ll[i++] = l = j; /* save last length in l */
1374 else if (j == 16) /* repeat last length 3 to 6 times */
1377 j = 3 + ((cab_ULONG)b & 3);
1379 if((cab_ULONG)i + j > n)
1384 else if (j == 17) /* 3 to 10 zero length codes */
1387 j = 3 + ((cab_ULONG)b & 7);
1389 if ((cab_ULONG)i + j > n)
1395 else /* j == 18: 11 to 138 zero length codes */
1398 j = 11 + ((cab_ULONG)b & 0x7f);
1400 if ((cab_ULONG)i + j > n)
1408 /* free decoding table for trees */
1409 fdi_Ziphuft_free(CAB(hfdi), tl);
1411 /* restore the global bit buffer */
1415 /* build the decoding tables for literal/length and distance codes */
1417 if((i = fdi_Ziphuft_build(ll, nl, 257, Zipcplens, Zipcplext, &tl, &bl, decomp_state)) != 0)
1420 fdi_Ziphuft_free(CAB(hfdi), tl);
1421 return i; /* incomplete code set */
1424 fdi_Ziphuft_build(ll + nl, nd, 0, Zipcpdist, Zipcpdext, &td, &bd, decomp_state);
1426 /* decompress until an end-of-block code */
1427 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1430 /* free the decoding tables, return */
1431 fdi_Ziphuft_free(CAB(hfdi), tl);
1432 fdi_Ziphuft_free(CAB(hfdi), td);
1436 /*****************************************************
1437 * fdi_Zipinflate_block (internal)
1439 static cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1440 { /* decompress an inflated block */
1441 cab_ULONG t; /* block type */
1442 register cab_ULONG b; /* bit buffer */
1443 register cab_ULONG k; /* number of bits in bit buffer */
1445 /* make local bit buffer */
1449 /* read in last block bit */
1451 *e = (cab_LONG)b & 1;
1454 /* read in block type */
1456 t = (cab_ULONG)b & 3;
1459 /* restore the global bit buffer */
1463 /* inflate that block type */
1465 return fdi_Zipinflate_dynamic(decomp_state);
1467 return fdi_Zipinflate_stored(decomp_state);
1469 return fdi_Zipinflate_fixed(decomp_state);
1470 /* bad block type */
1474 /****************************************************
1475 * ZIPfdi_decomp(internal)
1477 static int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1479 cab_LONG e; /* last block flag */
1481 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1483 ZIP(inpos) = CAB(inbuf);
1484 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1485 if(outlen > ZIPWSIZE)
1486 return DECR_DATAFORMAT;
1488 /* CK = Chris Kirmse, official Microsoft purloiner */
1489 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1490 return DECR_ILLEGALDATA;
1494 if(fdi_Zipinflate_block(&e, decomp_state))
1495 return DECR_ILLEGALDATA;
1498 /* return success */
1502 /*******************************************************************
1503 * QTMfdi_decomp(internal)
1505 static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1507 cab_UBYTE *inpos = CAB(inbuf);
1508 cab_UBYTE *window = QTM(window);
1509 cab_UBYTE *runsrc, *rundest;
1510 cab_ULONG window_posn = QTM(window_posn);
1511 cab_ULONG window_size = QTM(window_size);
1513 /* used by bitstream macros */
1514 register int bitsleft, bitrun, bitsneed;
1515 register cab_ULONG bitbuf;
1517 /* used by GET_SYMBOL */
1522 int extra, togo = outlen, match_length = 0, copy_length;
1523 cab_UBYTE selector, sym;
1524 cab_ULONG match_offset = 0;
1526 cab_UWORD H = 0xFFFF, L = 0, C;
1528 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1530 /* read initial value of C */
1534 /* apply 2^x-1 mask */
1535 window_posn &= window_size - 1;
1536 /* runs can't straddle the window wraparound */
1537 if ((window_posn + togo) > window_size) {
1538 TRACE("straddled run\n");
1539 return DECR_DATAFORMAT;
1543 GET_SYMBOL(model7, selector);
1546 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1549 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1552 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1555 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1559 /* selector 4 = fixed length of 3 */
1560 GET_SYMBOL(model4, sym);
1561 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1562 match_offset = CAB(q_position_base)[sym] + extra + 1;
1567 /* selector 5 = fixed length of 4 */
1568 GET_SYMBOL(model5, sym);
1569 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1570 match_offset = CAB(q_position_base)[sym] + extra + 1;
1575 /* selector 6 = variable length */
1576 GET_SYMBOL(model6len, sym);
1577 Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1578 match_length = CAB(q_length_base)[sym] + extra + 5;
1579 GET_SYMBOL(model6pos, sym);
1580 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1581 match_offset = CAB(q_position_base)[sym] + extra + 1;
1585 TRACE("Selector is bogus\n");
1586 return DECR_ILLEGALDATA;
1589 /* if this is a match */
1590 if (selector >= 4) {
1591 rundest = window + window_posn;
1592 togo -= match_length;
1594 /* copy any wrapped around source data */
1595 if (window_posn >= match_offset) {
1597 runsrc = rundest - match_offset;
1599 runsrc = rundest + (window_size - match_offset);
1600 copy_length = match_offset - window_posn;
1601 if (copy_length < match_length) {
1602 match_length -= copy_length;
1603 window_posn += copy_length;
1604 while (copy_length-- > 0) *rundest++ = *runsrc++;
1608 window_posn += match_length;
1610 /* copy match data - no worries about destination wraps */
1611 while (match_length-- > 0) *rundest++ = *runsrc++;
1613 } /* while (togo > 0) */
1616 TRACE("Frame overflow, this_run = %d\n", togo);
1617 return DECR_ILLEGALDATA;
1620 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1623 QTM(window_posn) = window_posn;
1627 /************************************************************
1628 * fdi_lzx_read_lens (internal)
1630 static int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1631 fdi_decomp_state *decomp_state) {
1635 register cab_ULONG bitbuf = lb->bb;
1636 register int bitsleft = lb->bl;
1637 cab_UBYTE *inpos = lb->ip;
1640 for (x = 0; x < 20; x++) {
1642 LENTABLE(PRETREE)[x] = y;
1644 BUILD_TABLE(PRETREE);
1646 for (x = first; x < last; ) {
1647 READ_HUFFSYM(PRETREE, z);
1649 READ_BITS(y, 4); y += 4;
1650 while (y--) lens[x++] = 0;
1653 READ_BITS(y, 5); y += 20;
1654 while (y--) lens[x++] = 0;
1657 READ_BITS(y, 1); y += 4;
1658 READ_HUFFSYM(PRETREE, z);
1659 z = lens[x] - z; if (z < 0) z += 17;
1660 while (y--) lens[x++] = z;
1663 z = lens[x] - z; if (z < 0) z += 17;
1674 /*******************************************************
1675 * LZXfdi_decomp(internal)
1677 static int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1678 cab_UBYTE *inpos = CAB(inbuf);
1679 const cab_UBYTE *endinp = inpos + inlen;
1680 cab_UBYTE *window = LZX(window);
1681 cab_UBYTE *runsrc, *rundest;
1682 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1684 cab_ULONG window_posn = LZX(window_posn);
1685 cab_ULONG window_size = LZX(window_size);
1686 cab_ULONG R0 = LZX(R0);
1687 cab_ULONG R1 = LZX(R1);
1688 cab_ULONG R2 = LZX(R2);
1690 register cab_ULONG bitbuf;
1691 register int bitsleft;
1692 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1693 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1695 int togo = outlen, this_run, main_element, aligned_bits;
1696 int match_length, copy_length, length_footer, extra, verbatim_bits;
1698 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1702 /* read header if necessary */
1703 if (!LZX(header_read)) {
1705 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1706 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1707 LZX(header_read) = 1;
1710 /* main decoding loop */
1712 /* last block finished, new block expected */
1713 if (LZX(block_remaining) == 0) {
1714 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1715 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1719 READ_BITS(LZX(block_type), 3);
1722 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1724 switch (LZX(block_type)) {
1725 case LZX_BLOCKTYPE_ALIGNED:
1726 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1727 BUILD_TABLE(ALIGNED);
1728 /* rest of aligned header is same as verbatim */
1730 case LZX_BLOCKTYPE_VERBATIM:
1731 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1732 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1733 BUILD_TABLE(MAINTREE);
1734 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1736 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1737 BUILD_TABLE(LENGTH);
1740 case LZX_BLOCKTYPE_UNCOMPRESSED:
1741 LZX(intel_started) = 1; /* because we can't assume otherwise */
1742 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1743 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1744 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1745 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1746 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1750 return DECR_ILLEGALDATA;
1754 /* buffer exhaustion check */
1755 if (inpos > endinp) {
1756 /* it's possible to have a file where the next run is less than
1757 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1758 * in building the tables will exhaust the buffer, so we should
1759 * allow for this, but not allow those accidentally read bits to
1760 * be used (so we check that there are at least 16 bits
1761 * remaining - in this boundary case they aren't really part of
1762 * the compressed data)
1764 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1767 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1768 if (this_run > togo) this_run = togo;
1770 LZX(block_remaining) -= this_run;
1772 /* apply 2^x-1 mask */
1773 window_posn &= window_size - 1;
1774 /* runs can't straddle the window wraparound */
1775 if ((window_posn + this_run) > window_size)
1776 return DECR_DATAFORMAT;
1778 switch (LZX(block_type)) {
1780 case LZX_BLOCKTYPE_VERBATIM:
1781 while (this_run > 0) {
1782 READ_HUFFSYM(MAINTREE, main_element);
1784 if (main_element < LZX_NUM_CHARS) {
1785 /* literal: 0 to LZX_NUM_CHARS-1 */
1786 window[window_posn++] = main_element;
1790 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1791 main_element -= LZX_NUM_CHARS;
1793 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1794 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1795 READ_HUFFSYM(LENGTH, length_footer);
1796 match_length += length_footer;
1798 match_length += LZX_MIN_MATCH;
1800 match_offset = main_element >> 3;
1802 if (match_offset > 2) {
1803 /* not repeated offset */
1804 if (match_offset != 3) {
1805 extra = CAB(extra_bits)[match_offset];
1806 READ_BITS(verbatim_bits, extra);
1807 match_offset = CAB(lzx_position_base)[match_offset]
1808 - 2 + verbatim_bits;
1814 /* update repeated offset LRU queue */
1815 R2 = R1; R1 = R0; R0 = match_offset;
1817 else if (match_offset == 0) {
1820 else if (match_offset == 1) {
1822 R1 = R0; R0 = match_offset;
1824 else /* match_offset == 2 */ {
1826 R2 = R0; R0 = match_offset;
1829 rundest = window + window_posn;
1830 this_run -= match_length;
1832 /* copy any wrapped around source data */
1833 if (window_posn >= match_offset) {
1835 runsrc = rundest - match_offset;
1837 runsrc = rundest + (window_size - match_offset);
1838 copy_length = match_offset - window_posn;
1839 if (copy_length < match_length) {
1840 match_length -= copy_length;
1841 window_posn += copy_length;
1842 while (copy_length-- > 0) *rundest++ = *runsrc++;
1846 window_posn += match_length;
1848 /* copy match data - no worries about destination wraps */
1849 while (match_length-- > 0) *rundest++ = *runsrc++;
1854 case LZX_BLOCKTYPE_ALIGNED:
1855 while (this_run > 0) {
1856 READ_HUFFSYM(MAINTREE, main_element);
1858 if (main_element < LZX_NUM_CHARS) {
1859 /* literal: 0 to LZX_NUM_CHARS-1 */
1860 window[window_posn++] = main_element;
1864 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1865 main_element -= LZX_NUM_CHARS;
1867 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1868 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1869 READ_HUFFSYM(LENGTH, length_footer);
1870 match_length += length_footer;
1872 match_length += LZX_MIN_MATCH;
1874 match_offset = main_element >> 3;
1876 if (match_offset > 2) {
1877 /* not repeated offset */
1878 extra = CAB(extra_bits)[match_offset];
1879 match_offset = CAB(lzx_position_base)[match_offset] - 2;
1881 /* verbatim and aligned bits */
1883 READ_BITS(verbatim_bits, extra);
1884 match_offset += (verbatim_bits << 3);
1885 READ_HUFFSYM(ALIGNED, aligned_bits);
1886 match_offset += aligned_bits;
1888 else if (extra == 3) {
1889 /* aligned bits only */
1890 READ_HUFFSYM(ALIGNED, aligned_bits);
1891 match_offset += aligned_bits;
1893 else if (extra > 0) { /* extra==1, extra==2 */
1894 /* verbatim bits only */
1895 READ_BITS(verbatim_bits, extra);
1896 match_offset += verbatim_bits;
1898 else /* extra == 0 */ {
1903 /* update repeated offset LRU queue */
1904 R2 = R1; R1 = R0; R0 = match_offset;
1906 else if (match_offset == 0) {
1909 else if (match_offset == 1) {
1911 R1 = R0; R0 = match_offset;
1913 else /* match_offset == 2 */ {
1915 R2 = R0; R0 = match_offset;
1918 rundest = window + window_posn;
1919 this_run -= match_length;
1921 /* copy any wrapped around source data */
1922 if (window_posn >= match_offset) {
1924 runsrc = rundest - match_offset;
1926 runsrc = rundest + (window_size - match_offset);
1927 copy_length = match_offset - window_posn;
1928 if (copy_length < match_length) {
1929 match_length -= copy_length;
1930 window_posn += copy_length;
1931 while (copy_length-- > 0) *rundest++ = *runsrc++;
1935 window_posn += match_length;
1937 /* copy match data - no worries about destination wraps */
1938 while (match_length-- > 0) *rundest++ = *runsrc++;
1943 case LZX_BLOCKTYPE_UNCOMPRESSED:
1944 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1945 memcpy(window + window_posn, inpos, (size_t) this_run);
1946 inpos += this_run; window_posn += this_run;
1950 return DECR_ILLEGALDATA; /* might as well */
1956 if (togo != 0) return DECR_ILLEGALDATA;
1957 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1958 outlen, (size_t) outlen);
1960 LZX(window_posn) = window_posn;
1965 /* intel E8 decoding */
1966 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1967 if (outlen <= 6 || !LZX(intel_started)) {
1968 LZX(intel_curpos) += outlen;
1971 cab_UBYTE *data = CAB(outbuf);
1972 cab_UBYTE *dataend = data + outlen - 10;
1973 cab_LONG curpos = LZX(intel_curpos);
1974 cab_LONG filesize = LZX(intel_filesize);
1975 cab_LONG abs_off, rel_off;
1977 LZX(intel_curpos) = curpos + outlen;
1979 while (data < dataend) {
1980 if (*data++ != 0xE8) { curpos++; continue; }
1981 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1982 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1983 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1984 data[0] = (cab_UBYTE) rel_off;
1985 data[1] = (cab_UBYTE) (rel_off >> 8);
1986 data[2] = (cab_UBYTE) (rel_off >> 16);
1987 data[3] = (cab_UBYTE) (rel_off >> 24);
1997 /**********************************************************
1998 * fdi_decomp (internal)
2000 * Decompress the requested number of bytes. If savemode is zero,
2001 * do not save the output anywhere, just plow through blocks until we
2002 * reach the specified (uncompressed) distance from the starting point,
2003 * and remember the position of the cabfile pointer (and which cabfile)
2004 * after we are done; otherwise, save the data out to CAB(filehf),
2005 * decompressing the requested number of bytes and writing them out. This
2006 * is also where we jump to additional cabinets in the case of split
2007 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
2009 static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
2010 char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
2012 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
2013 cab_UBYTE buf[cfdata_SIZEOF], *data;
2014 cab_UWORD inlen, len, outlen, cando;
2017 fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
2019 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
2022 /* cando = the max number of bytes we can do */
2023 cando = CAB(outlen);
2024 if (cando > bytes) cando = bytes;
2027 if (cando && savemode)
2028 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
2030 CAB(outpos) += cando;
2031 CAB(outlen) -= cando;
2032 bytes -= cando; if (!bytes) break;
2034 /* we only get here if we emptied the output buffer */
2036 /* read data header + data */
2038 while (outlen == 0) {
2039 /* read the block header, skip the reserved part */
2040 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
2043 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
2046 /* we shouldn't get blocks over CAB_INPUTMAX in size */
2047 data = CAB(inbuf) + inlen;
2048 len = EndGetI16(buf+cfdata_CompressedSize);
2050 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
2051 if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
2054 /* clear two bytes after read-in data */
2055 data[len+1] = data[len+2] = 0;
2057 /* perform checksum test on the block (if one is stored) */
2058 cksum = EndGetI32(buf+cfdata_CheckSum);
2059 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
2060 return DECR_CHECKSUM; /* checksum is wrong */
2062 outlen = EndGetI16(buf+cfdata_UncompressedSize);
2064 /* outlen=0 means this block was the last contiguous part
2065 of a split block, continued in the next cabinet */
2067 int pathlen, filenamelen, idx, i, cabhf;
2068 char fullpath[MAX_PATH], userpath[256];
2069 FDINOTIFICATION fdin;
2070 FDICABINETINFO fdici;
2071 char emptystring = '\0';
2073 int success = FALSE;
2074 struct fdi_folder *fol = NULL, *linkfol = NULL;
2075 struct fdi_file *file = NULL, *linkfile = NULL;
2079 /* set up the next decomp_state... */
2081 if (!cab->mii.hasnext) return DECR_INPUT;
2083 if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
2084 return DECR_NOMEMORY;
2086 ZeroMemory(cab->next, sizeof(fdi_decomp_state));
2088 /* copy pszCabPath to userpath */
2089 ZeroMemory(userpath, 256);
2090 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2092 if (pathlen < 256) {
2093 for (i = 0; i <= pathlen; i++)
2094 userpath[i] = pszCabPath[i];
2095 } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2098 /* initial fdintNEXT_CABINET notification */
2099 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2100 fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
2101 fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
2102 fdin.psz3 = &userpath[0];
2103 fdin.fdie = FDIERROR_NONE;
2106 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2110 pathlen = strlen(userpath);
2111 filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
2113 /* slight overestimation here to save CPU cycles in the developer's brain */
2114 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2115 ERR("MAX_PATH exceeded.\n");
2116 return DECR_ILLEGALDATA;
2119 /* paste the path and filename together */
2122 for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
2123 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2125 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
2126 fullpath[idx] = '\0';
2128 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2130 /* try to get a handle to the cabfile */
2131 cabhf = PFDI_OPEN(CAB(hfdi), fullpath, 32768, _S_IREAD | _S_IWRITE);
2133 /* no file. allow the user to try again */
2134 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2135 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2140 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2141 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2142 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2146 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2147 if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
2148 WARN("FDIIsCabinet failed.\n");
2149 PFDI_CLOSE(CAB(hfdi), cabhf);
2150 fdin.fdie = FDIERROR_NOT_A_CABINET;
2151 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2155 if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
2156 WARN("Wrong Cabinet.\n");
2157 PFDI_CLOSE(CAB(hfdi), cabhf);
2158 fdin.fdie = FDIERROR_WRONG_CABINET;
2159 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2167 /* cabinet notification */
2168 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2169 fdin.setID = fdici.setID;
2170 fdin.iCabinet = fdici.iCabinet;
2172 fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2173 fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2174 fdin.psz3 = pszCabPath;
2176 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2178 cab->next->setID = fdici.setID;
2179 cab->next->iCabinet = fdici.iCabinet;
2180 cab->next->hfdi = CAB(hfdi);
2181 cab->next->filehf = CAB(filehf);
2182 cab->next->cabhf = cabhf;
2183 cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2185 cab = cab->next; /* advance to the next cabinet */
2188 for (i = 0; i < fdici.cFolders; i++) {
2189 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF)
2192 if (cab->mii.folder_resv > 0)
2193 PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2195 fol = (struct fdi_folder *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2197 ERR("out of memory!\n");
2198 return DECR_NOMEMORY;
2200 ZeroMemory(fol, sizeof(struct fdi_folder));
2201 if (!(cab->firstfol)) cab->firstfol = fol;
2203 fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2204 fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2205 fol->comp_type = EndGetI16(buf2+cffold_CompType);
2208 linkfol->next = fol;
2213 for (i = 0; i < fdici.cFiles; i++) {
2214 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2217 file = (struct fdi_file *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2219 ERR("out of memory!\n");
2220 return DECR_NOMEMORY;
2222 ZeroMemory(file, sizeof(struct fdi_file));
2223 if (!(cab->firstfile)) cab->firstfile = file;
2225 file->length = EndGetI32(buf2+cffile_UncompressedSize);
2226 file->offset = EndGetI32(buf2+cffile_FolderOffset);
2227 file->index = EndGetI16(buf2+cffile_FolderIndex);
2228 file->time = EndGetI16(buf2+cffile_Time);
2229 file->date = EndGetI16(buf2+cffile_Date);
2230 file->attribs = EndGetI16(buf2+cffile_Attribs);
2231 file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2233 if (!file->filename) return DECR_INPUT;
2236 linkfile->next = file;
2241 cab = cab->next; /* advance to the next cabinet */
2243 /* iterate files -- if we encounter the continued file, process it --
2244 otherwise, jump to the label above and keep looking */
2246 for (file = cab->firstfile; (file); file = file->next) {
2247 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2248 /* check to ensure a real match */
2249 if (strcasecmp(fi->filename, file->filename) == 0) {
2251 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2257 if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2258 "Wrong Cabinet" notification? */
2262 /* decompress block */
2263 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2265 CAB(outlen) = outlen;
2266 CAB(outpos) = CAB(outbuf);
2269 CAB(decomp_cab) = cab;
2273 /***********************************************************************
2274 * FDICopy (CABINET.22)
2276 * Iterates through the files in the Cabinet file indicated by name and
2277 * file-location. May chain forward to additional cabinets (typically
2278 * only one) if files which begin in this Cabinet are continued in another
2279 * cabinet. For each file which is partially contained in this cabinet,
2280 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2281 * notification to the pfnfdin callback. For each file which begins in
2282 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2283 * callback, and the file is optionally decompressed and saved to disk.
2284 * Notification is not provided for files which are not at least partially
2285 * contained in the specified cabinet file.
2287 * See below for a thorough explanation of the various notification
2291 * hfdi [I] An HFDI from FDICreate
2292 * pszCabinet [I] C-style string containing the filename of the cabinet
2293 * pszCabPath [I] C-style string containing the file path of the cabinet
2294 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2295 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2296 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2298 * pvUser [I] arbitrary void * value which is passed to callbacks.
2301 * TRUE if successful.
2302 * FALSE if unsuccessful (error information is provided in the ERF structure
2303 * associated with the provided decompression handle by FDICreate).
2307 * Two pointers to callback functions are provided as parameters to FDICopy:
2308 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2309 * types are as follows:
2311 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2312 * PFDINOTIFICATION pfdin );
2314 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2316 * You can create functions of this type using the FNFDINOTIFY() and
2317 * FNFDIDECRYPT() macros, respectively. For example:
2319 * FNFDINOTIFY(mycallback) {
2320 * / * use variables fdint and pfdin to process notification * /
2323 * The second callback, which could be used for decrypting encrypted data,
2324 * is not used at all.
2326 * Each notification informs the user of some event which has occurred during
2327 * decompression of the cabinet file; each notification is also an opportunity
2328 * for the callee to abort decompression. The information provided to the
2329 * callback and the meaning of the callback's return value vary drastically
2330 * across the various types of notification. The type of notification is the
2331 * fdint parameter; all other information is provided to the callback in
2332 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2333 * pfdin. The only part of that structure which is assigned for every callback
2334 * is the pv element, which contains the arbitrary value which was passed to
2335 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2336 * is highly dependent on fdint).
2338 * If you encounter unknown notifications, you should return zero if you want
2339 * decompression to continue (or -1 to abort). All strings used in the
2340 * callbacks are regular C-style strings. Detailed descriptions of each
2341 * notification type follow:
2343 * fdintCABINET_INFO:
2345 * This is the first notification provided after calling FDICopy, and provides
2346 * the user with various information about the cabinet. Note that this is
2347 * called for each cabinet FDICopy opens, not just the first one. In the
2348 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2349 * next cabinet file in the set after the one just loaded (if any), psz2
2350 * contains a pointer to the name or "info" of the next disk, psz3
2351 * contains a pointer to the file-path of the current cabinet, setID
2352 * contains an arbitrary constant associated with this set of cabinet files,
2353 * and iCabinet contains the numerical index of the current cabinet within
2354 * that set. Return zero, or -1 to abort.
2356 * fdintPARTIAL_FILE:
2358 * This notification is provided when FDICopy encounters a part of a file
2359 * contained in this cabinet which is missing its beginning. Files can be
2360 * split across cabinets, so this is not necessarily an abnormality; it just
2361 * means that the file in question begins in another cabinet. No file
2362 * corresponding to this notification is extracted from the cabinet. In the
2363 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2364 * partial file, psz2 contains a pointer to the file name of the cabinet in
2365 * which this file begins, and psz3 contains a pointer to the disk name or
2366 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2370 * This notification is provided when FDICopy encounters a file which starts
2371 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2372 * look for files in cabinets after the first one). One notification will be
2373 * sent for each such file, before the file is decompressed. By returning
2374 * zero, the callback can instruct FDICopy to skip the file. In the structure
2375 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2376 * the size of the file (uncompressed), attribs contains the file attributes,
2377 * and date and time contain the date and time of the file. attributes, date,
2378 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2379 * for the entire cabinet, 0 to skip just this file but continue scanning the
2380 * cabinet for more files, or an FDIClose()-compatible file-handle.
2382 * fdintCLOSE_FILE_INFO:
2384 * This notification is important, don't forget to implement it. This
2385 * notification indicates that a file has been successfully uncompressed and
2386 * written to disk. Upon receipt of this notification, the callee is expected
2387 * to close the file handle, to set the attributes and date/time of the
2388 * closed file, and possibly to execute the file. In the structure pointed to
2389 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2390 * open file handle (close it), cb contains 1 or zero, indicating respectively
2391 * that the callee should or should not execute the file, and date, time
2392 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2393 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2394 * do so. Return TRUE, or FALSE to abort decompression.
2396 * fdintNEXT_CABINET:
2398 * This notification is called when FDICopy must load in another cabinet. This
2399 * can occur when a file's data is "split" across multiple cabinets. The
2400 * callee has the opportunity to request that FDICopy look in a different file
2401 * path for the specified cabinet file, by writing that data into a provided
2402 * buffer (see below for more information). This notification will be received
2403 * more than once per-cabinet in the instance that FDICopy failed to find a
2404 * valid cabinet at the location specified by the first per-cabinet
2405 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2406 * structure pointed to by pfdin indicates the error which prevented FDICopy
2407 * from proceeding successfully. Return zero to indicate success, or -1 to
2408 * indicate failure and abort FDICopy.
2410 * Upon receipt of this notification, the structure pointed to by pfdin will
2411 * contain the following values: psz1 pointing to the name of the cabinet
2412 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2413 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2414 * and fdie containing either FDIERROR_NONE, or one of the following:
2416 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2417 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2418 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2419 * FDIERROR_WRONG_CABINET.
2421 * The callee may choose to change the path where FDICopy will look for the
2422 * cabinet after this notification. To do so, the caller may write the new
2423 * pathname to the buffer pointed to by psz3, which is 256 characters in
2424 * length, including the terminating null character, before returning zero.
2428 * Undocumented and unimplemented in wine, this seems to be sent each time
2429 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2430 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2431 * provides information about the current cabinet instead of the next one....
2432 * this is just a guess, it has not been looked at closely.
2437 BOOL __cdecl FDICopy(
2442 PFNFDINOTIFY pfnfdin,
2443 PFNFDIDECRYPT pfnfdid,
2446 FDICABINETINFO fdici;
2447 FDINOTIFICATION fdin;
2448 int cabhf, filehf = 0, idx;
2450 char fullpath[MAX_PATH];
2451 size_t pathlen, filenamelen;
2452 char emptystring = '\0';
2454 struct fdi_folder *fol = NULL, *linkfol = NULL;
2455 struct fdi_file *file = NULL, *linkfile = NULL;
2456 fdi_decomp_state _decomp_state;
2457 fdi_decomp_state *decomp_state = &_decomp_state;
2459 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, "
2460 "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2461 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2463 if (!REALLY_IS_FDI(hfdi)) {
2464 SetLastError(ERROR_INVALID_HANDLE);
2468 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2470 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2471 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2473 /* slight overestimation here to save CPU cycles in the developer's brain */
2474 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2475 ERR("MAX_PATH exceeded.\n");
2476 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2477 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2478 PFDI_INT(hfdi)->perf->fError = TRUE;
2479 SetLastError(ERROR_FILE_NOT_FOUND);
2483 /* paste the path and filename together */
2486 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2487 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2489 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2490 fullpath[idx] = '\0';
2492 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2494 /* get a handle to the cabfile */
2495 cabhf = PFDI_OPEN(hfdi, fullpath, 32768, _S_IREAD | _S_IWRITE);
2497 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2498 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2499 PFDI_INT(hfdi)->perf->fError = TRUE;
2500 SetLastError(ERROR_FILE_NOT_FOUND);
2505 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2506 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2507 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2508 PFDI_INT(hfdi)->perf->fError = TRUE;
2509 SetLastError(ERROR_FILE_NOT_FOUND);
2513 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2514 if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2515 ERR("FDIIsCabinet failed.\n");
2516 PFDI_CLOSE(hfdi, cabhf);
2520 /* cabinet notification */
2521 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2522 fdin.setID = fdici.setID;
2523 fdin.iCabinet = fdici.iCabinet;
2525 fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2526 fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2527 fdin.psz3 = pszCabPath;
2529 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2530 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2531 PFDI_INT(hfdi)->perf->erfType = 0;
2532 PFDI_INT(hfdi)->perf->fError = TRUE;
2536 CAB(setID) = fdici.setID;
2537 CAB(iCabinet) = fdici.iCabinet;
2541 for (i = 0; i < fdici.cFolders; i++) {
2542 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2543 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2544 PFDI_INT(hfdi)->perf->erfType = 0;
2545 PFDI_INT(hfdi)->perf->fError = TRUE;
2549 if (CAB(mii).folder_resv > 0)
2550 PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2552 fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2554 ERR("out of memory!\n");
2555 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2556 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2557 PFDI_INT(hfdi)->perf->fError = TRUE;
2558 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2561 ZeroMemory(fol, sizeof(struct fdi_folder));
2562 if (!CAB(firstfol)) CAB(firstfol) = fol;
2564 fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2565 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2566 fol->comp_type = EndGetI16(buf+cffold_CompType);
2569 linkfol->next = fol;
2574 for (i = 0; i < fdici.cFiles; i++) {
2575 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2576 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2577 PFDI_INT(hfdi)->perf->erfType = 0;
2578 PFDI_INT(hfdi)->perf->fError = TRUE;
2582 file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2584 ERR("out of memory!\n");
2585 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2586 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2587 PFDI_INT(hfdi)->perf->fError = TRUE;
2588 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2591 ZeroMemory(file, sizeof(struct fdi_file));
2592 if (!CAB(firstfile)) CAB(firstfile) = file;
2594 file->length = EndGetI32(buf+cffile_UncompressedSize);
2595 file->offset = EndGetI32(buf+cffile_FolderOffset);
2596 file->index = EndGetI16(buf+cffile_FolderIndex);
2597 file->time = EndGetI16(buf+cffile_Time);
2598 file->date = EndGetI16(buf+cffile_Date);
2599 file->attribs = EndGetI16(buf+cffile_Attribs);
2600 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2602 if (!file->filename) {
2603 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2604 PFDI_INT(hfdi)->perf->erfType = 0;
2605 PFDI_INT(hfdi)->perf->fError = TRUE;
2610 linkfile->next = file;
2614 for (file = CAB(firstfile); (file); file = file->next) {
2617 * FIXME: This implementation keeps multiple cabinet files open at once
2618 * when encountering a split cabinet. It is a quirk of this implementation
2619 * that sometimes we decrypt the same block of data more than once, to find
2620 * the right starting point for a file, moving the file-pointer backwards.
2621 * If we kept a cache of certain file-pointer information, we could eliminate
2622 * that behavior... in fact I am not sure that the caching we already have
2623 * is not sufficient.
2625 * The current implementation seems to work fine in straightforward situations
2626 * where all the cabinet files needed for decryption are simultaneously
2627 * available. But presumably, the API is supposed to support cabinets which
2628 * are split across multiple CDROMS; we may need to change our implementation
2629 * to strictly serialize it's file usage so that it opens only one cabinet
2630 * at a time. Some experimentation with Windows is needed to figure out the
2631 * precise semantics required. The relevant code is here and in fdi_decomp().
2634 /* partial-file notification */
2635 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2637 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2638 * and perform some tests to figure out the right behavior. The SDK says
2639 * FDICopy will notify the user of the filename and "disk name" (info) of
2640 * the cabinet where the spanning file /started/.
2642 * That would certainly be convenient for the API-user, who could abort,
2643 * everything (or parallelize, if that's allowed (it is in wine)), and call
2644 * FDICopy again with the provided filename, so as to avoid partial file
2645 * notification and successfully unpack. This task could be quite unpleasant
2646 * from wine's perspective: the information specifying the "start cabinet" for
2647 * a file is associated nowhere with the file header and is not to be found in
2648 * the cabinet header. We have only the index of the cabinet wherein the folder
2649 * begins, which contains the file. To find that cabinet, we must consider the
2650 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2651 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2654 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2655 * cabinet other than the active one might be at another filepath than the
2656 * current one, or on another CDROM. This could get rather dicey, especially
2657 * if we imagine parallelized access to the FDICopy API.
2659 * The current implementation punts -- it just returns the previous cabinet and
2660 * it's info from the header of this cabinet. This provides the right answer in
2661 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2664 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2666 fdin.psz1 = (char *)file->filename;
2667 fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2668 fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2670 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2671 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2672 PFDI_INT(hfdi)->perf->erfType = 0;
2673 PFDI_INT(hfdi)->perf->fError = TRUE;
2676 /* I don't think we are supposed to decompress partial files. This prevents it. */
2677 file->oppressed = TRUE;
2679 if (file->oppressed) {
2682 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2684 fdin.psz1 = (char *)file->filename;
2685 fdin.cb = file->length;
2686 fdin.date = file->date;
2687 fdin.time = file->time;
2688 fdin.attribs = file->attribs;
2689 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2690 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2691 PFDI_INT(hfdi)->perf->erfType = 0;
2692 PFDI_INT(hfdi)->perf->fError = TRUE;
2697 /* find the folder for this file if necc. */
2701 fol = CAB(firstfol);
2702 if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2703 /* pick the last folder */
2704 while (fol->next) fol = fol->next;
2706 for (i2 = 0; (i2 < file->index); i2++)
2707 if (fol->next) /* bug resistance, should always be true */
2713 cab_UWORD comptype = fol->comp_type;
2714 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2715 int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2718 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2720 /* set up decomp_state */
2722 CAB(filehf) = filehf;
2724 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2725 if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2727 TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2729 /* free stuff for the old decompresser */
2731 case cffoldCOMPTYPE_LZX:
2733 PFDI_FREE(hfdi, LZX(window));
2737 case cffoldCOMPTYPE_QUANTUM:
2739 PFDI_FREE(hfdi, QTM(window));
2745 CAB(decomp_cab) = NULL;
2746 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2750 /* initialize the new decompresser */
2752 case cffoldCOMPTYPE_NONE:
2753 CAB(decompress) = NONEfdi_decomp;
2755 case cffoldCOMPTYPE_MSZIP:
2756 CAB(decompress) = ZIPfdi_decomp;
2758 case cffoldCOMPTYPE_QUANTUM:
2759 CAB(decompress) = QTMfdi_decomp;
2760 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2762 case cffoldCOMPTYPE_LZX:
2763 CAB(decompress) = LZXfdi_decomp;
2764 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2767 err = DECR_DATAFORMAT;
2777 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2778 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2779 PFDI_INT(hfdi)->perf->fError = TRUE;
2780 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2783 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2784 PFDI_INT(hfdi)->perf->erfOper = 0;
2785 PFDI_INT(hfdi)->perf->fError = TRUE;
2789 if (file->offset > CAB(offset)) {
2790 /* decode bytes and send them to /dev/null */
2791 switch ((err = fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser))) {
2794 case DECR_USERABORT:
2795 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2796 PFDI_INT(hfdi)->perf->erfType = 0;
2797 PFDI_INT(hfdi)->perf->fError = TRUE;
2800 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2801 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2802 PFDI_INT(hfdi)->perf->fError = TRUE;
2803 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2806 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2807 PFDI_INT(hfdi)->perf->erfOper = 0;
2808 PFDI_INT(hfdi)->perf->fError = TRUE;
2811 CAB(offset) = file->offset;
2814 /* now do the actual decompression */
2815 err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2816 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2818 /* fdintCLOSE_FILE_INFO notification */
2819 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2821 fdin.psz1 = (char *)file->filename;
2823 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2824 fdin.date = file->date;
2825 fdin.time = file->time;
2826 fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2827 ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2833 case DECR_USERABORT:
2834 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2835 PFDI_INT(hfdi)->perf->erfType = 0;
2836 PFDI_INT(hfdi)->perf->fError = TRUE;
2839 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2840 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2841 PFDI_INT(hfdi)->perf->fError = TRUE;
2842 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2845 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2846 PFDI_INT(hfdi)->perf->erfOper = 0;
2847 PFDI_INT(hfdi)->perf->fError = TRUE;
2853 /* free decompression temps */
2854 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2855 case cffoldCOMPTYPE_LZX:
2857 PFDI_FREE(hfdi, LZX(window));
2861 case cffoldCOMPTYPE_QUANTUM:
2863 PFDI_FREE(hfdi, QTM(window));
2869 while (decomp_state) {
2870 fdi_decomp_state *prev_fds;
2872 PFDI_CLOSE(hfdi, CAB(cabhf));
2874 /* free the storage remembered by mii */
2875 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2876 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2877 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2878 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2880 while (CAB(firstfol)) {
2881 fol = CAB(firstfol);
2882 CAB(firstfol) = CAB(firstfol)->next;
2883 PFDI_FREE(hfdi, fol);
2885 while (CAB(firstfile)) {
2886 file = CAB(firstfile);
2887 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2888 CAB(firstfile) = CAB(firstfile)->next;
2889 PFDI_FREE(hfdi, file);
2891 prev_fds = decomp_state;
2892 decomp_state = CAB(next);
2893 if (prev_fds != &_decomp_state)
2894 PFDI_FREE(hfdi, prev_fds);
2899 bail_and_fail: /* here we free ram before error returns */
2901 /* free decompression temps */
2902 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2903 case cffoldCOMPTYPE_LZX:
2905 PFDI_FREE(hfdi, LZX(window));
2909 case cffoldCOMPTYPE_QUANTUM:
2911 PFDI_FREE(hfdi, QTM(window));
2917 if (filehf) PFDI_CLOSE(hfdi, filehf);
2919 while (decomp_state) {
2920 fdi_decomp_state *prev_fds;
2922 PFDI_CLOSE(hfdi, CAB(cabhf));
2924 /* free the storage remembered by mii */
2925 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2926 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2927 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2928 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2930 while (CAB(firstfol)) {
2931 fol = CAB(firstfol);
2932 CAB(firstfol) = CAB(firstfol)->next;
2933 PFDI_FREE(hfdi, fol);
2935 while (CAB(firstfile)) {
2936 file = CAB(firstfile);
2937 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2938 CAB(firstfile) = CAB(firstfile)->next;
2939 PFDI_FREE(hfdi, file);
2941 prev_fds = decomp_state;
2942 decomp_state = CAB(next);
2943 if (prev_fds != &_decomp_state)
2944 PFDI_FREE(hfdi, prev_fds);
2950 /***********************************************************************
2951 * FDIDestroy (CABINET.23)
2953 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2954 * of FDICopy. Only reason for failure would be an invalid handle.
2957 * hfdi [I] The HFDI to free
2963 BOOL __cdecl FDIDestroy(HFDI hfdi)
2965 TRACE("(hfdi == ^%p)\n", hfdi);
2966 if (REALLY_IS_FDI(hfdi)) {
2967 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2968 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2971 SetLastError(ERROR_INVALID_HANDLE);
2976 /***********************************************************************
2977 * FDITruncateCabinet (CABINET.24)
2979 * Removes all folders of a cabinet file after and including the
2980 * specified folder number.
2983 * hfdi [I] Handle to the FDI context.
2984 * pszCabinetName [I] Filename of the cabinet.
2985 * iFolderToDelete [I] Index of the first folder to delete.
2992 * The PFNWRITE function supplied to FDICreate must truncate the
2993 * file at the current position if the number of bytes to write is 0.
2995 BOOL __cdecl FDITruncateCabinet(
2997 char *pszCabinetName,
2998 USHORT iFolderToDelete)
3000 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
3001 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
3003 if (!REALLY_IS_FDI(hfdi)) {
3004 SetLastError(ERROR_INVALID_HANDLE);
3008 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);