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_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];
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 static 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 static int make_decode_table(cab_ULONG nsyms, cab_ULONG nbits,
224 const cab_UBYTE *length, cab_UWORD *table) {
225 register cab_UWORD sym;
226 register cab_ULONG leaf;
227 register cab_UBYTE bit_num = 1;
229 cab_ULONG pos = 0; /* the current position in the decode table */
230 cab_ULONG table_mask = 1 << nbits;
231 cab_ULONG bit_mask = table_mask >> 1; /* don't do 0 length codes */
232 cab_ULONG next_symbol = bit_mask; /* base of allocation for long codes */
234 /* fill entries for codes short enough for a direct mapping */
235 while (bit_num <= nbits) {
236 for (sym = 0; sym < nsyms; sym++) {
237 if (length[sym] == bit_num) {
240 if((pos += bit_mask) > table_mask) return 1; /* table overrun */
242 /* fill all possible lookups of this symbol with the symbol itself */
244 while (fill-- > 0) table[leaf++] = sym;
251 /* if there are any codes longer than nbits */
252 if (pos != table_mask) {
253 /* clear the remainder of the table */
254 for (sym = pos; sym < table_mask; sym++) table[sym] = 0;
256 /* give ourselves room for codes to grow by up to 16 more bits */
261 while (bit_num <= 16) {
262 for (sym = 0; sym < nsyms; sym++) {
263 if (length[sym] == bit_num) {
265 for (fill = 0; fill < bit_num - nbits; fill++) {
266 /* if this path hasn't been taken yet, 'allocate' two entries */
267 if (table[leaf] == 0) {
268 table[(next_symbol << 1)] = 0;
269 table[(next_symbol << 1) + 1] = 0;
270 table[leaf] = next_symbol++;
272 /* follow the path and select either left or right for next bit */
273 leaf = table[leaf] << 1;
274 if ((pos >> (15-fill)) & 1) leaf++;
278 if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
287 if (pos == table_mask) return 0;
289 /* either erroneous table, or all elements are 0 - let's find out. */
290 for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1;
294 /*************************************************************************
295 * checksum (internal)
297 static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum) {
301 for (len = bytes >> 2; len--; data += 4) {
302 csum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
306 case 3: ul |= *data++ << 16;
307 case 2: ul |= *data++ << 8;
315 /***********************************************************************
316 * FDICreate (CABINET.20)
318 * Provided with several callbacks (all of them are mandatory),
319 * returns a handle which can be used to perform operations
323 * pfnalloc [I] A pointer to a function which allocates ram. Uses
324 * the same interface as malloc.
325 * pfnfree [I] A pointer to a function which frees ram. Uses the
326 * same interface as free.
327 * pfnopen [I] A pointer to a function which opens a file. Uses
328 * the same interface as _open.
329 * pfnread [I] A pointer to a function which reads from a file into
330 * a caller-provided buffer. Uses the same interface
332 * pfnwrite [I] A pointer to a function which writes to a file from
333 * a caller-provided buffer. Uses the same interface
335 * pfnclose [I] A pointer to a function which closes a file handle.
336 * Uses the same interface as _close.
337 * pfnseek [I] A pointer to a function which seeks in a file.
338 * Uses the same interface as _lseek.
339 * cpuType [I] The type of CPU; ignored in wine (recommended value:
340 * cpuUNKNOWN, aka -1).
341 * perf [IO] A pointer to an ERF structure. When FDICreate
342 * returns an error condition, error information may
343 * be found here as well as from GetLastError.
346 * On success, returns an FDI handle of type HFDI.
347 * On failure, the NULL file handle is returned. Error
348 * info can be retrieved from perf.
354 HFDI __cdecl FDICreate(
367 TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, "
368 "pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
369 pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
372 if ((!pfnalloc) || (!pfnfree)) {
373 perf->erfOper = FDIERROR_NONE;
374 perf->erfType = ERROR_BAD_ARGUMENTS;
377 SetLastError(ERROR_BAD_ARGUMENTS);
381 if (!((rv = (*pfnalloc)(sizeof(FDI_Int))))) {
382 perf->erfOper = FDIERROR_ALLOC_FAIL;
383 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
386 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
390 PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
391 PFDI_INT(rv)->pfnalloc = pfnalloc;
392 PFDI_INT(rv)->pfnfree = pfnfree;
393 PFDI_INT(rv)->pfnopen = pfnopen;
394 PFDI_INT(rv)->pfnread = pfnread;
395 PFDI_INT(rv)->pfnwrite = pfnwrite;
396 PFDI_INT(rv)->pfnclose = pfnclose;
397 PFDI_INT(rv)->pfnseek = pfnseek;
398 /* no-brainer: we ignore the cpu type; this is only used
399 for the 16-bit versions in Windows anyhow... */
400 PFDI_INT(rv)->perf = perf;
405 /*******************************************************************
406 * FDI_getoffset (internal)
408 * returns the file pointer position of a file handle.
410 static long FDI_getoffset(HFDI hfdi, INT_PTR hf)
412 return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
415 /**********************************************************************
416 * FDI_read_string (internal)
418 * allocate and read an arbitrarily long string from the cabinet
420 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
423 base = FDI_getoffset(hfdi, hf),
424 maxlen = cabsize - base;
427 cab_UBYTE *buf = NULL;
429 TRACE("(hfdi == ^%p, hf == %ld, cabsize == %ld)\n", hfdi, hf, cabsize);
432 if (len > maxlen) len = maxlen;
433 if (!(buf = PFDI_ALLOC(hfdi, len))) break;
434 if (!PFDI_READ(hfdi, hf, buf, len)) break;
436 /* search for a null terminator in what we've just read */
437 for (i=0; i < len; i++) {
438 if (!buf[i]) {ok=TRUE; break;}
443 ERR("cabinet is truncated\n");
446 /* The buffer is too small for the string. Reset the file to the point
447 * were we started, free the buffer and increase the size for the next try
449 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
450 PFDI_FREE(hfdi, buf);
458 PFDI_FREE(hfdi, buf);
460 ERR("out of memory!\n");
464 /* otherwise, set the stream to just after the string and return */
465 PFDI_SEEK(hfdi, hf, base + strlen((char *)buf) + 1, SEEK_SET);
470 /******************************************************************
471 * FDI_read_entries (internal)
473 * process the cabinet header in the style of FDIIsCabinet, but
474 * without the sanity checks (and bug)
476 static BOOL FDI_read_entries(
479 PFDICABINETINFO pfdici,
480 PMORE_ISCAB_INFO pmii)
482 int num_folders, num_files, header_resv, folder_resv = 0;
483 LONG base_offset, cabsize;
484 USHORT setid, cabidx, flags;
485 cab_UBYTE buf[64], block_resv;
486 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
488 TRACE("(hfdi == ^%p, hf == %ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
491 * FIXME: I just noticed that I am memorizing the initial file pointer
492 * offset and restoring it before reading in the rest of the header
493 * information in the cabinet. Perhaps that's correct -- that is, perhaps
494 * this API is supposed to support "streaming" cabinets which are embedded
495 * in other files, or cabinets which begin at file offsets other than zero.
496 * Otherwise, I should instead go to the absolute beginning of the file.
497 * (Either way, the semantics of wine's FDICopy require me to leave the
498 * file pointer where it is afterwards -- If Windows does not do so, we
499 * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
501 * So, the answer lies in Windows; will native cabinet.dll recognize a
502 * cabinet "file" embedded in another file? Note that cabextract.c does
503 * support this, which implies that Microsoft's might. I haven't tried it
504 * yet so I don't know. ATM, most of wine's FDI cabinet routines (except
505 * this one) would not work in this way. To fix it, we could just make the
506 * various references to absolute file positions in the code relative to an
507 * initial "beginning" offset. Because the FDICopy API doesn't take a
508 * file-handle like this one, we would therein need to search through the
509 * file for the beginning of the cabinet (as we also do in cabextract.c).
510 * Note that this limits us to a maximum of one cabinet per. file: the first.
512 * So, in summary: either the code below is wrong, or the rest of fdi.c is
513 * wrong... I cannot imagine that both are correct ;) One of these flaws
514 * should be fixed after determining the behavior on Windows. We ought
515 * to check both FDIIsCabinet and FDICopy for the right behavior.
520 /* get basic offset & size info */
521 base_offset = FDI_getoffset(hfdi, hf);
523 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
525 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
526 PFDI_INT(hfdi)->perf->erfType = 0;
527 PFDI_INT(hfdi)->perf->fError = TRUE;
532 cabsize = FDI_getoffset(hfdi, hf);
534 if ((cabsize == -1) || (base_offset == -1) ||
535 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
537 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
538 PFDI_INT(hfdi)->perf->erfType = 0;
539 PFDI_INT(hfdi)->perf->fError = TRUE;
544 /* read in the CFHEADER */
545 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
547 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
548 PFDI_INT(hfdi)->perf->erfType = 0;
549 PFDI_INT(hfdi)->perf->fError = TRUE;
554 /* check basic MSCF signature */
555 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
557 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
558 PFDI_INT(hfdi)->perf->erfType = 0;
559 PFDI_INT(hfdi)->perf->fError = TRUE;
564 /* get the number of folders */
565 num_folders = EndGetI16(buf+cfhead_NumFolders);
566 if (num_folders == 0) {
567 /* PONDERME: is this really invalid? */
568 WARN("weird cabinet detect failure: no folders in cabinet\n");
570 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
571 PFDI_INT(hfdi)->perf->erfType = 0;
572 PFDI_INT(hfdi)->perf->fError = TRUE;
577 /* get the number of files */
578 num_files = EndGetI16(buf+cfhead_NumFiles);
579 if (num_files == 0) {
580 /* PONDERME: is this really invalid? */
581 WARN("weird cabinet detect failure: no files in cabinet\n");
583 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
584 PFDI_INT(hfdi)->perf->erfType = 0;
585 PFDI_INT(hfdi)->perf->fError = TRUE;
591 setid = EndGetI16(buf+cfhead_SetID);
593 /* cabinet (set) index */
594 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
596 /* check the header revision */
597 if ((buf[cfhead_MajorVersion] > 1) ||
598 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
600 WARN("cabinet format version > 1.3\n");
602 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
603 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
604 PFDI_INT(hfdi)->perf->fError = TRUE;
609 /* pull the flags out */
610 flags = EndGetI16(buf+cfhead_Flags);
612 /* read the reserved-sizes part of header, if present */
613 if (flags & cfheadRESERVE_PRESENT) {
614 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
615 ERR("bunk reserve-sizes?\n");
617 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
618 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
619 PFDI_INT(hfdi)->perf->fError = TRUE;
624 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
625 if (pmii) pmii->header_resv = header_resv;
626 folder_resv = buf[cfheadext_FolderReserved];
627 if (pmii) pmii->folder_resv = folder_resv;
628 block_resv = buf[cfheadext_DataReserved];
629 if (pmii) pmii->block_resv = block_resv;
631 if (header_resv > 60000) {
632 WARN("WARNING; header reserved space > 60000\n");
635 /* skip the reserved header */
636 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
637 ERR("seek failure: header_resv\n");
639 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
640 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
641 PFDI_INT(hfdi)->perf->fError = TRUE;
647 if (flags & cfheadPREV_CABINET) {
648 prevname = FDI_read_string(hfdi, hf, cabsize);
651 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
652 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
653 PFDI_INT(hfdi)->perf->fError = TRUE;
658 pmii->prevname = prevname;
660 PFDI_FREE(hfdi, prevname);
661 previnfo = FDI_read_string(hfdi, hf, cabsize);
664 pmii->previnfo = previnfo;
666 PFDI_FREE(hfdi, previnfo);
670 if (flags & cfheadNEXT_CABINET) {
672 pmii->hasnext = TRUE;
673 nextname = FDI_read_string(hfdi, hf, cabsize);
675 if ((flags & cfheadPREV_CABINET) && pmii) {
676 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
677 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
679 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
680 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
681 PFDI_INT(hfdi)->perf->fError = TRUE;
685 pmii->nextname = nextname;
687 PFDI_FREE(hfdi, nextname);
688 nextinfo = FDI_read_string(hfdi, hf, cabsize);
691 pmii->nextinfo = nextinfo;
693 PFDI_FREE(hfdi, nextinfo);
697 /* we could process the whole cabinet searching for problems;
698 instead lets stop here. Now let's fill out the paperwork */
699 pfdici->cbCabinet = cabsize;
700 pfdici->cFolders = num_folders;
701 pfdici->cFiles = num_files;
702 pfdici->setID = setid;
703 pfdici->iCabinet = cabidx;
704 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
705 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
706 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
710 /***********************************************************************
711 * FDIIsCabinet (CABINET.21)
713 * Informs the caller as to whether or not the provided file handle is
714 * really a cabinet or not, filling out the provided PFDICABINETINFO
715 * structure with information about the cabinet. Brief explanations of
716 * the elements of this structure are available as comments accompanying
717 * its definition in wine's include/fdi.h.
720 * hfdi [I] An HFDI from FDICreate
721 * hf [I] The file handle about which the caller inquires
722 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
723 * be filled out with information about the cabinet
724 * file indicated by hf if, indeed, it is determined
728 * TRUE if the file is a cabinet. The info pointed to by pfdici will
730 * FALSE if the file is not a cabinet, or if an error was encountered
731 * while processing the cabinet. The PERF structure provided to
732 * FDICreate can be queried for more error information.
737 BOOL __cdecl FDIIsCabinet(
740 PFDICABINETINFO pfdici)
744 TRACE("(hfdi == ^%p, hf == ^%ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
746 if (!REALLY_IS_FDI(hfdi)) {
747 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
748 SetLastError(ERROR_INVALID_HANDLE);
754 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
755 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
756 PFDI_INT(hfdi)->perf->fError = TRUE; */
757 SetLastError(ERROR_INVALID_HANDLE);
763 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
764 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
765 PFDI_INT(hfdi)->perf->fError = TRUE; */
766 SetLastError(ERROR_BAD_ARGUMENTS);
769 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
772 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
777 /******************************************************************
778 * QTMfdi_initmodel (internal)
780 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
782 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
787 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
788 for (i = 0; i < n; i++) {
789 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
790 m->syms[i].sym = i+s; /* actual symbol */
791 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
793 m->syms[n].cumfreq = 0;
796 /******************************************************************
797 * QTMfdi_init (internal)
799 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
800 unsigned int wndsize = 1 << window;
801 int msz = window * 2, i;
804 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
805 /* if a previously allocated window is big enough, keep it */
806 if (window < 10 || window > 21) return DECR_DATAFORMAT;
807 if (QTM(actual_size) < wndsize) {
808 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
812 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
813 QTM(actual_size) = wndsize;
815 QTM(window_size) = wndsize;
816 QTM(window_posn) = 0;
818 /* initialize static slot/extrabits tables */
819 for (i = 0, j = 0; i < 27; i++) {
820 CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
821 CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
823 for (i = 0, j = 0; i < 42; i++) {
824 CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
825 CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
828 /* initialize arithmetic coding models */
830 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
832 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
833 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
834 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
835 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
837 /* model 4 depends on table size, ranges from 20 to 24 */
838 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
839 /* model 5 depends on table size, ranges from 20 to 36 */
840 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
841 /* model 6pos depends on table size, ranges from 20 to 42 */
842 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
843 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
848 /************************************************************
849 * LZXfdi_init (internal)
851 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
852 static const cab_UBYTE bits[] =
853 { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
854 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
855 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
857 static const cab_ULONG base[] =
858 { 0, 1, 2, 3, 4, 6, 8, 12,
859 16, 24, 32, 48, 64, 96, 128, 192,
860 256, 384, 512, 768, 1024, 1536, 2048, 3072,
861 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
862 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
863 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
864 1835008, 1966080, 2097152};
865 cab_ULONG wndsize = 1 << window;
868 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
869 /* if a previously allocated window is big enough, keep it */
870 if (window < 15 || window > 21) return DECR_DATAFORMAT;
871 if (LZX(actual_size) < wndsize) {
872 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
876 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
877 LZX(actual_size) = wndsize;
879 LZX(window_size) = wndsize;
881 /* initialize static tables */
882 memcpy(CAB(extra_bits), bits, sizeof(bits));
883 memcpy(CAB(lzx_position_base), base, sizeof(base));
885 /* calculate required position slots */
886 if (window == 20) posn_slots = 42;
887 else if (window == 21) posn_slots = 50;
888 else posn_slots = window << 1;
890 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
892 LZX(R0) = LZX(R1) = LZX(R2) = 1;
893 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
894 LZX(header_read) = 0;
895 LZX(frames_read) = 0;
896 LZX(block_remaining) = 0;
897 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
898 LZX(intel_curpos) = 0;
899 LZX(intel_started) = 0;
900 LZX(window_posn) = 0;
902 /* initialize tables to 0 (because deltas will be applied to them) */
903 memset(LZX(MAINTREE_len), 0, sizeof(LZX(MAINTREE_len)));
904 memset(LZX(LENGTH_len), 0, sizeof(LZX(LENGTH_len)));
909 /****************************************************
910 * NONEfdi_decomp(internal)
912 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
914 if (inlen != outlen) return DECR_ILLEGALDATA;
915 if (outlen > CAB_BLOCKMAX) return DECR_DATAFORMAT;
916 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
920 /********************************************************
921 * Ziphuft_free (internal)
923 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
925 register struct Ziphuft *p, *q;
927 /* Go through linked list, freeing from the allocated (t[-1]) address. */
937 /*********************************************************
938 * fdi_Ziphuft_build (internal)
940 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, const cab_UWORD *d, const cab_UWORD *e,
941 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
943 cab_ULONG a; /* counter for codes of length k */
944 cab_ULONG el; /* length of EOB code (value 256) */
945 cab_ULONG f; /* i repeats in table every f entries */
946 cab_LONG g; /* maximum code length */
947 cab_LONG h; /* table level */
948 register cab_ULONG i; /* counter, current code */
949 register cab_ULONG j; /* counter */
950 register cab_LONG k; /* number of bits in current code */
951 cab_LONG *l; /* stack of bits per table */
952 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
953 register struct Ziphuft *q; /* points to current table */
954 struct Ziphuft r; /* table entry for structure assignment */
955 register cab_LONG w; /* bits before this table == (l * h) */
956 cab_ULONG *xp; /* pointer into x */
957 cab_LONG y; /* number of dummy codes added */
958 cab_ULONG z; /* number of entries in current table */
962 /* Generate counts for each bit length */
963 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
965 for(i = 0; i < ZIPBMAX+1; ++i)
970 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
972 if (ZIP(c)[0] == n) /* null input--all zero length codes */
979 /* Find minimum and maximum length, bound *m by those */
980 for (j = 1; j <= ZIPBMAX; j++)
983 k = j; /* minimum code length */
984 if ((cab_ULONG)*m < j)
986 for (i = ZIPBMAX; i; i--)
989 g = i; /* maximum code length */
990 if ((cab_ULONG)*m > i)
993 /* Adjust last length count to fill out codes, if needed */
994 for (y = 1 << j; j < i; j++, y <<= 1)
995 if ((y -= ZIP(c)[j]) < 0)
996 return 2; /* bad input: more codes than bits */
997 if ((y -= ZIP(c)[i]) < 0)
1001 /* Generate starting offsets LONGo the value table for each length */
1003 p = ZIP(c) + 1; xp = ZIP(x) + 2;
1005 { /* note that i == g from above */
1006 *xp++ = (j += *p++);
1009 /* Make a table of values in order of bit lengths */
1012 if ((j = *p++) != 0)
1013 ZIP(v)[ZIP(x)[j]++] = i;
1017 /* Generate the Huffman codes and for each, make the table entries */
1018 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
1019 p = ZIP(v); /* grab values in bit order */
1020 h = -1; /* no tables yet--level -1 */
1021 w = l[-1] = 0; /* no bits decoded yet */
1022 ZIP(u)[0] = NULL; /* just to keep compilers happy */
1023 q = NULL; /* ditto */
1026 /* go through the bit lengths (k already is bits in shortest code) */
1032 /* here i is the Huffman code of length k bits for value *p */
1033 /* make tables up to required level */
1034 while (k > w + l[h])
1036 w += l[h++]; /* add bits already decoded */
1038 /* compute minimum size table less than or equal to *m bits */
1039 if ((z = g - w) > (cab_ULONG)*m) /* upper limit */
1041 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
1042 { /* too few codes for k-w bit table */
1043 f -= a + 1; /* deduct codes from patterns left */
1045 while (++j < z) /* try smaller tables up to z bits */
1047 if ((f <<= 1) <= *++xp)
1048 break; /* enough codes to use up j bits */
1049 f -= *xp; /* else deduct codes from patterns */
1052 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
1053 j = el - w; /* make EOB code end at table */
1054 z = 1 << j; /* table entries for j-bit table */
1055 l[h] = j; /* set table size in stack */
1057 /* allocate and link in new table */
1058 if (!(q = PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
1061 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
1062 return 3; /* not enough memory */
1064 *t = q + 1; /* link to list for Ziphuft_free() */
1065 *(t = &(q->v.t)) = NULL;
1066 ZIP(u)[h] = ++q; /* table starts after link */
1068 /* connect to last table, if there is one */
1071 ZIP(x)[h] = i; /* save pattern for backing up */
1072 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
1073 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
1074 r.v.t = q; /* pointer to this table */
1075 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
1076 ZIP(u)[h-1][j] = r; /* connect to last table */
1080 /* set up table entry in r */
1081 r.b = (cab_UBYTE)(k - w);
1082 if (p >= ZIP(v) + n)
1083 r.e = 99; /* out of values--invalid code */
1086 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
1087 r.v.n = *p++; /* simple code is just the value */
1091 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
1092 r.v.n = d[*p++ - s];
1095 /* fill code-like entries with r */
1097 for (j = i >> w; j < z; j += f)
1100 /* backwards increment the k-bit code i */
1101 for (j = 1 << (k - 1); i & j; j >>= 1)
1105 /* backup over finished tables */
1106 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
1107 w -= l[--h]; /* don't need to update q */
1111 /* return actual size of base table */
1114 /* Return true (1) if we were given an incomplete table */
1115 return y != 0 && g != 1;
1118 /*********************************************************
1119 * fdi_Zipinflate_codes (internal)
1121 static cab_LONG fdi_Zipinflate_codes(const struct Ziphuft *tl, const struct Ziphuft *td,
1122 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
1124 register cab_ULONG e; /* table entry flag/number of extra bits */
1125 cab_ULONG n, d; /* length and index for copy */
1126 cab_ULONG w; /* current window position */
1127 const struct Ziphuft *t; /* pointer to table entry */
1128 cab_ULONG ml, md; /* masks for bl and bd bits */
1129 register cab_ULONG b; /* bit buffer */
1130 register cab_ULONG k; /* number of bits in bit buffer */
1132 /* make local copies of globals */
1133 b = ZIP(bb); /* initialize bit buffer */
1135 w = ZIP(window_posn); /* initialize window position */
1137 /* inflate the coded data */
1138 ml = Zipmask[bl]; /* precompute masks for speed */
1143 ZIPNEEDBITS((cab_ULONG)bl)
1144 if((e = (t = tl + (b & ml))->e) > 16)
1152 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1154 if (e == 16) /* then it's a literal */
1155 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
1156 else /* it's an EOB or a length */
1158 /* exit if end of block */
1162 /* get length of block to copy */
1164 n = t->v.n + (b & Zipmask[e]);
1167 /* decode distance of block to copy */
1168 ZIPNEEDBITS((cab_ULONG)bd)
1169 if ((e = (t = td + (b & md))->e) > 16)
1176 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1179 d = w - t->v.n - (b & Zipmask[e]);
1184 e = ZIPWSIZE - max(d, w);
1189 CAB(outbuf)[w++] = CAB(outbuf)[d++];
1195 /* restore the globals from the locals */
1196 ZIP(window_posn) = w; /* restore global window pointer */
1197 ZIP(bb) = b; /* restore global bit buffer */
1204 /***********************************************************
1205 * Zipinflate_stored (internal)
1207 static cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1208 /* "decompress" an inflated type 0 (stored) block. */
1210 cab_ULONG n; /* number of bytes in block */
1211 cab_ULONG w; /* current window position */
1212 register cab_ULONG b; /* bit buffer */
1213 register cab_ULONG k; /* number of bits in bit buffer */
1215 /* make local copies of globals */
1216 b = ZIP(bb); /* initialize bit buffer */
1218 w = ZIP(window_posn); /* initialize window position */
1220 /* go to byte boundary */
1224 /* get the length and its complement */
1229 if (n != ((~b) & 0xffff))
1230 return 1; /* error in compressed data */
1233 /* read and output the compressed data */
1237 CAB(outbuf)[w++] = (cab_UBYTE)b;
1241 /* restore the globals from the locals */
1242 ZIP(window_posn) = w; /* restore global window pointer */
1243 ZIP(bb) = b; /* restore global bit buffer */
1248 /******************************************************
1249 * fdi_Zipinflate_fixed (internal)
1251 static cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1253 struct Ziphuft *fixed_tl;
1254 struct Ziphuft *fixed_td;
1255 cab_LONG fixed_bl, fixed_bd;
1256 cab_LONG i; /* temporary variable */
1262 for(i = 0; i < 144; i++)
1268 for(; i < 288; i++) /* make a complete, but wrong code set */
1271 if((i = fdi_Ziphuft_build(l, 288, 257, Zipcplens, Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1274 /* distance table */
1275 for(i = 0; i < 30; i++) /* make an incomplete code set */
1278 if((i = fdi_Ziphuft_build(l, 30, 0, Zipcpdist, Zipcpdext, &fixed_td, &fixed_bd, decomp_state)) > 1)
1280 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1284 /* decompress until an end-of-block code */
1285 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1287 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1288 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1292 /**************************************************************
1293 * fdi_Zipinflate_dynamic (internal)
1295 static cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1296 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1298 cab_LONG i; /* temporary variables */
1301 cab_ULONG l; /* last length */
1302 cab_ULONG m; /* mask for bit lengths table */
1303 cab_ULONG n; /* number of lengths to get */
1304 struct Ziphuft *tl; /* literal/length code table */
1305 struct Ziphuft *td; /* distance code table */
1306 cab_LONG bl; /* lookup bits for tl */
1307 cab_LONG bd; /* lookup bits for td */
1308 cab_ULONG nb; /* number of bit length codes */
1309 cab_ULONG nl; /* number of literal/length codes */
1310 cab_ULONG nd; /* number of distance codes */
1311 register cab_ULONG b; /* bit buffer */
1312 register cab_ULONG k; /* number of bits in bit buffer */
1314 /* make local bit buffer */
1319 /* read in table lengths */
1321 nl = 257 + (b & 0x1f); /* number of literal/length codes */
1324 nd = 1 + (b & 0x1f); /* number of distance codes */
1327 nb = 4 + (b & 0xf); /* number of bit length codes */
1329 if(nl > 288 || nd > 32)
1330 return 1; /* bad lengths */
1332 /* read in bit-length-code lengths */
1333 for(j = 0; j < nb; j++)
1336 ll[Zipborder[j]] = b & 7;
1340 ll[Zipborder[j]] = 0;
1342 /* build decoding table for trees--single level, 7 bit lookup */
1344 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1347 fdi_Ziphuft_free(CAB(hfdi), tl);
1348 return i; /* incomplete code set */
1351 /* read in literal and distance code lengths */
1355 while((cab_ULONG)i < n)
1357 ZIPNEEDBITS((cab_ULONG)bl)
1358 j = (td = tl + (b & m))->b;
1361 if (j < 16) /* length of code in bits (0..15) */
1362 ll[i++] = l = j; /* save last length in l */
1363 else if (j == 16) /* repeat last length 3 to 6 times */
1368 if((cab_ULONG)i + j > n)
1373 else if (j == 17) /* 3 to 10 zero length codes */
1378 if ((cab_ULONG)i + j > n)
1384 else /* j == 18: 11 to 138 zero length codes */
1387 j = 11 + (b & 0x7f);
1389 if ((cab_ULONG)i + j > n)
1397 /* free decoding table for trees */
1398 fdi_Ziphuft_free(CAB(hfdi), tl);
1400 /* restore the global bit buffer */
1404 /* build the decoding tables for literal/length and distance codes */
1406 if((i = fdi_Ziphuft_build(ll, nl, 257, Zipcplens, Zipcplext, &tl, &bl, decomp_state)) != 0)
1409 fdi_Ziphuft_free(CAB(hfdi), tl);
1410 return i; /* incomplete code set */
1413 fdi_Ziphuft_build(ll + nl, nd, 0, Zipcpdist, Zipcpdext, &td, &bd, decomp_state);
1415 /* decompress until an end-of-block code */
1416 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1419 /* free the decoding tables, return */
1420 fdi_Ziphuft_free(CAB(hfdi), tl);
1421 fdi_Ziphuft_free(CAB(hfdi), td);
1425 /*****************************************************
1426 * fdi_Zipinflate_block (internal)
1428 static cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1429 { /* decompress an inflated block */
1430 cab_ULONG t; /* block type */
1431 register cab_ULONG b; /* bit buffer */
1432 register cab_ULONG k; /* number of bits in bit buffer */
1434 /* make local bit buffer */
1438 /* read in last block bit */
1440 *e = (cab_LONG)b & 1;
1443 /* read in block type */
1448 /* restore the global bit buffer */
1452 /* inflate that block type */
1454 return fdi_Zipinflate_dynamic(decomp_state);
1456 return fdi_Zipinflate_stored(decomp_state);
1458 return fdi_Zipinflate_fixed(decomp_state);
1459 /* bad block type */
1463 /****************************************************
1464 * ZIPfdi_decomp(internal)
1466 static int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1468 cab_LONG e; /* last block flag */
1470 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1472 ZIP(inpos) = CAB(inbuf);
1473 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1474 if(outlen > ZIPWSIZE)
1475 return DECR_DATAFORMAT;
1477 /* CK = Chris Kirmse, official Microsoft purloiner */
1478 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1479 return DECR_ILLEGALDATA;
1483 if(fdi_Zipinflate_block(&e, decomp_state))
1484 return DECR_ILLEGALDATA;
1487 /* return success */
1491 /*******************************************************************
1492 * QTMfdi_decomp(internal)
1494 static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1496 cab_UBYTE *inpos = CAB(inbuf);
1497 cab_UBYTE *window = QTM(window);
1498 cab_UBYTE *runsrc, *rundest;
1499 cab_ULONG window_posn = QTM(window_posn);
1500 cab_ULONG window_size = QTM(window_size);
1502 /* used by bitstream macros */
1503 register int bitsleft, bitrun, bitsneed;
1504 register cab_ULONG bitbuf;
1506 /* used by GET_SYMBOL */
1511 int extra, togo = outlen, match_length = 0, copy_length;
1512 cab_UBYTE selector, sym;
1513 cab_ULONG match_offset = 0;
1515 cab_UWORD H = 0xFFFF, L = 0, C;
1517 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1519 /* read initial value of C */
1523 /* apply 2^x-1 mask */
1524 window_posn &= window_size - 1;
1525 /* runs can't straddle the window wraparound */
1526 if ((window_posn + togo) > window_size) {
1527 TRACE("straddled run\n");
1528 return DECR_DATAFORMAT;
1532 GET_SYMBOL(model7, selector);
1535 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1538 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1541 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1544 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1548 /* selector 4 = fixed length of 3 */
1549 GET_SYMBOL(model4, sym);
1550 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1551 match_offset = CAB(q_position_base)[sym] + extra + 1;
1556 /* selector 5 = fixed length of 4 */
1557 GET_SYMBOL(model5, sym);
1558 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1559 match_offset = CAB(q_position_base)[sym] + extra + 1;
1564 /* selector 6 = variable length */
1565 GET_SYMBOL(model6len, sym);
1566 Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1567 match_length = CAB(q_length_base)[sym] + extra + 5;
1568 GET_SYMBOL(model6pos, sym);
1569 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1570 match_offset = CAB(q_position_base)[sym] + extra + 1;
1574 TRACE("Selector is bogus\n");
1575 return DECR_ILLEGALDATA;
1578 /* if this is a match */
1579 if (selector >= 4) {
1580 rundest = window + window_posn;
1581 togo -= match_length;
1583 /* copy any wrapped around source data */
1584 if (window_posn >= match_offset) {
1586 runsrc = rundest - match_offset;
1588 runsrc = rundest + (window_size - match_offset);
1589 copy_length = match_offset - window_posn;
1590 if (copy_length < match_length) {
1591 match_length -= copy_length;
1592 window_posn += copy_length;
1593 while (copy_length-- > 0) *rundest++ = *runsrc++;
1597 window_posn += match_length;
1599 /* copy match data - no worries about destination wraps */
1600 while (match_length-- > 0) *rundest++ = *runsrc++;
1602 } /* while (togo > 0) */
1605 TRACE("Frame overflow, this_run = %d\n", togo);
1606 return DECR_ILLEGALDATA;
1609 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1612 QTM(window_posn) = window_posn;
1616 /************************************************************
1617 * fdi_lzx_read_lens (internal)
1619 static int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1620 fdi_decomp_state *decomp_state) {
1624 register cab_ULONG bitbuf = lb->bb;
1625 register int bitsleft = lb->bl;
1626 cab_UBYTE *inpos = lb->ip;
1629 for (x = 0; x < 20; x++) {
1631 LENTABLE(PRETREE)[x] = y;
1633 BUILD_TABLE(PRETREE);
1635 for (x = first; x < last; ) {
1636 READ_HUFFSYM(PRETREE, z);
1638 READ_BITS(y, 4); y += 4;
1639 while (y--) lens[x++] = 0;
1642 READ_BITS(y, 5); y += 20;
1643 while (y--) lens[x++] = 0;
1646 READ_BITS(y, 1); y += 4;
1647 READ_HUFFSYM(PRETREE, z);
1648 z = lens[x] - z; if (z < 0) z += 17;
1649 while (y--) lens[x++] = z;
1652 z = lens[x] - z; if (z < 0) z += 17;
1663 /*******************************************************
1664 * LZXfdi_decomp(internal)
1666 static int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1667 cab_UBYTE *inpos = CAB(inbuf);
1668 const cab_UBYTE *endinp = inpos + inlen;
1669 cab_UBYTE *window = LZX(window);
1670 cab_UBYTE *runsrc, *rundest;
1671 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1673 cab_ULONG window_posn = LZX(window_posn);
1674 cab_ULONG window_size = LZX(window_size);
1675 cab_ULONG R0 = LZX(R0);
1676 cab_ULONG R1 = LZX(R1);
1677 cab_ULONG R2 = LZX(R2);
1679 register cab_ULONG bitbuf;
1680 register int bitsleft;
1681 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1682 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1684 int togo = outlen, this_run, main_element, aligned_bits;
1685 int match_length, copy_length, length_footer, extra, verbatim_bits;
1687 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1691 /* read header if necessary */
1692 if (!LZX(header_read)) {
1694 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1695 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1696 LZX(header_read) = 1;
1699 /* main decoding loop */
1701 /* last block finished, new block expected */
1702 if (LZX(block_remaining) == 0) {
1703 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1704 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1708 READ_BITS(LZX(block_type), 3);
1711 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1713 switch (LZX(block_type)) {
1714 case LZX_BLOCKTYPE_ALIGNED:
1715 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1716 BUILD_TABLE(ALIGNED);
1717 /* rest of aligned header is same as verbatim */
1719 case LZX_BLOCKTYPE_VERBATIM:
1720 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1721 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1722 BUILD_TABLE(MAINTREE);
1723 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1725 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1726 BUILD_TABLE(LENGTH);
1729 case LZX_BLOCKTYPE_UNCOMPRESSED:
1730 LZX(intel_started) = 1; /* because we can't assume otherwise */
1731 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1732 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1733 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1734 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1735 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1739 return DECR_ILLEGALDATA;
1743 /* buffer exhaustion check */
1744 if (inpos > endinp) {
1745 /* it's possible to have a file where the next run is less than
1746 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1747 * in building the tables will exhaust the buffer, so we should
1748 * allow for this, but not allow those accidentally read bits to
1749 * be used (so we check that there are at least 16 bits
1750 * remaining - in this boundary case they aren't really part of
1751 * the compressed data)
1753 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1756 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1757 if (this_run > togo) this_run = togo;
1759 LZX(block_remaining) -= this_run;
1761 /* apply 2^x-1 mask */
1762 window_posn &= window_size - 1;
1763 /* runs can't straddle the window wraparound */
1764 if ((window_posn + this_run) > window_size)
1765 return DECR_DATAFORMAT;
1767 switch (LZX(block_type)) {
1769 case LZX_BLOCKTYPE_VERBATIM:
1770 while (this_run > 0) {
1771 READ_HUFFSYM(MAINTREE, main_element);
1773 if (main_element < LZX_NUM_CHARS) {
1774 /* literal: 0 to LZX_NUM_CHARS-1 */
1775 window[window_posn++] = main_element;
1779 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1780 main_element -= LZX_NUM_CHARS;
1782 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1783 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1784 READ_HUFFSYM(LENGTH, length_footer);
1785 match_length += length_footer;
1787 match_length += LZX_MIN_MATCH;
1789 match_offset = main_element >> 3;
1791 if (match_offset > 2) {
1792 /* not repeated offset */
1793 if (match_offset != 3) {
1794 extra = CAB(extra_bits)[match_offset];
1795 READ_BITS(verbatim_bits, extra);
1796 match_offset = CAB(lzx_position_base)[match_offset]
1797 - 2 + verbatim_bits;
1803 /* update repeated offset LRU queue */
1804 R2 = R1; R1 = R0; R0 = match_offset;
1806 else if (match_offset == 0) {
1809 else if (match_offset == 1) {
1811 R1 = R0; R0 = match_offset;
1813 else /* match_offset == 2 */ {
1815 R2 = R0; R0 = match_offset;
1818 rundest = window + window_posn;
1819 this_run -= match_length;
1821 /* copy any wrapped around source data */
1822 if (window_posn >= match_offset) {
1824 runsrc = rundest - match_offset;
1826 runsrc = rundest + (window_size - match_offset);
1827 copy_length = match_offset - window_posn;
1828 if (copy_length < match_length) {
1829 match_length -= copy_length;
1830 window_posn += copy_length;
1831 while (copy_length-- > 0) *rundest++ = *runsrc++;
1835 window_posn += match_length;
1837 /* copy match data - no worries about destination wraps */
1838 while (match_length-- > 0) *rundest++ = *runsrc++;
1843 case LZX_BLOCKTYPE_ALIGNED:
1844 while (this_run > 0) {
1845 READ_HUFFSYM(MAINTREE, main_element);
1847 if (main_element < LZX_NUM_CHARS) {
1848 /* literal: 0 to LZX_NUM_CHARS-1 */
1849 window[window_posn++] = main_element;
1853 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1854 main_element -= LZX_NUM_CHARS;
1856 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1857 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1858 READ_HUFFSYM(LENGTH, length_footer);
1859 match_length += length_footer;
1861 match_length += LZX_MIN_MATCH;
1863 match_offset = main_element >> 3;
1865 if (match_offset > 2) {
1866 /* not repeated offset */
1867 extra = CAB(extra_bits)[match_offset];
1868 match_offset = CAB(lzx_position_base)[match_offset] - 2;
1870 /* verbatim and aligned bits */
1872 READ_BITS(verbatim_bits, extra);
1873 match_offset += (verbatim_bits << 3);
1874 READ_HUFFSYM(ALIGNED, aligned_bits);
1875 match_offset += aligned_bits;
1877 else if (extra == 3) {
1878 /* aligned bits only */
1879 READ_HUFFSYM(ALIGNED, aligned_bits);
1880 match_offset += aligned_bits;
1882 else if (extra > 0) { /* extra==1, extra==2 */
1883 /* verbatim bits only */
1884 READ_BITS(verbatim_bits, extra);
1885 match_offset += verbatim_bits;
1887 else /* extra == 0 */ {
1892 /* update repeated offset LRU queue */
1893 R2 = R1; R1 = R0; R0 = match_offset;
1895 else if (match_offset == 0) {
1898 else if (match_offset == 1) {
1900 R1 = R0; R0 = match_offset;
1902 else /* match_offset == 2 */ {
1904 R2 = R0; R0 = match_offset;
1907 rundest = window + window_posn;
1908 this_run -= match_length;
1910 /* copy any wrapped around source data */
1911 if (window_posn >= match_offset) {
1913 runsrc = rundest - match_offset;
1915 runsrc = rundest + (window_size - match_offset);
1916 copy_length = match_offset - window_posn;
1917 if (copy_length < match_length) {
1918 match_length -= copy_length;
1919 window_posn += copy_length;
1920 while (copy_length-- > 0) *rundest++ = *runsrc++;
1924 window_posn += match_length;
1926 /* copy match data - no worries about destination wraps */
1927 while (match_length-- > 0) *rundest++ = *runsrc++;
1932 case LZX_BLOCKTYPE_UNCOMPRESSED:
1933 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1934 memcpy(window + window_posn, inpos, (size_t) this_run);
1935 inpos += this_run; window_posn += this_run;
1939 return DECR_ILLEGALDATA; /* might as well */
1945 if (togo != 0) return DECR_ILLEGALDATA;
1946 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1947 outlen, (size_t) outlen);
1949 LZX(window_posn) = window_posn;
1954 /* intel E8 decoding */
1955 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1956 if (outlen <= 6 || !LZX(intel_started)) {
1957 LZX(intel_curpos) += outlen;
1960 cab_UBYTE *data = CAB(outbuf);
1961 cab_UBYTE *dataend = data + outlen - 10;
1962 cab_LONG curpos = LZX(intel_curpos);
1963 cab_LONG filesize = LZX(intel_filesize);
1964 cab_LONG abs_off, rel_off;
1966 LZX(intel_curpos) = curpos + outlen;
1968 while (data < dataend) {
1969 if (*data++ != 0xE8) { curpos++; continue; }
1970 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1971 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1972 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1973 data[0] = (cab_UBYTE) rel_off;
1974 data[1] = (cab_UBYTE) (rel_off >> 8);
1975 data[2] = (cab_UBYTE) (rel_off >> 16);
1976 data[3] = (cab_UBYTE) (rel_off >> 24);
1986 /**********************************************************
1987 * fdi_decomp (internal)
1989 * Decompress the requested number of bytes. If savemode is zero,
1990 * do not save the output anywhere, just plow through blocks until we
1991 * reach the specified (uncompressed) distance from the starting point,
1992 * and remember the position of the cabfile pointer (and which cabfile)
1993 * after we are done; otherwise, save the data out to CAB(filehf),
1994 * decompressing the requested number of bytes and writing them out. This
1995 * is also where we jump to additional cabinets in the case of split
1996 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1998 static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
1999 char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
2001 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
2002 cab_UBYTE buf[cfdata_SIZEOF], *data;
2003 cab_UWORD inlen, len, outlen, cando;
2006 fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
2008 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
2011 /* cando = the max number of bytes we can do */
2012 cando = CAB(outlen);
2013 if (cando > bytes) cando = bytes;
2016 if (cando && savemode)
2017 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
2019 CAB(outpos) += cando;
2020 CAB(outlen) -= cando;
2021 bytes -= cando; if (!bytes) break;
2023 /* we only get here if we emptied the output buffer */
2025 /* read data header + data */
2027 while (outlen == 0) {
2028 /* read the block header, skip the reserved part */
2029 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
2032 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
2035 /* we shouldn't get blocks over CAB_INPUTMAX in size */
2036 data = CAB(inbuf) + inlen;
2037 len = EndGetI16(buf+cfdata_CompressedSize);
2039 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
2040 if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
2043 /* clear two bytes after read-in data */
2044 data[len+1] = data[len+2] = 0;
2046 /* perform checksum test on the block (if one is stored) */
2047 cksum = EndGetI32(buf+cfdata_CheckSum);
2048 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
2049 return DECR_CHECKSUM; /* checksum is wrong */
2051 outlen = EndGetI16(buf+cfdata_UncompressedSize);
2053 /* outlen=0 means this block was the last contiguous part
2054 of a split block, continued in the next cabinet */
2056 int pathlen, filenamelen, idx, i;
2058 char fullpath[MAX_PATH], userpath[256];
2059 FDINOTIFICATION fdin;
2060 FDICABINETINFO fdici;
2061 char emptystring = '\0';
2063 int success = FALSE;
2064 struct fdi_folder *fol = NULL, *linkfol = NULL;
2065 struct fdi_file *file = NULL, *linkfile = NULL;
2069 /* set up the next decomp_state... */
2071 if (!cab->mii.hasnext) return DECR_INPUT;
2073 if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
2074 return DECR_NOMEMORY;
2076 ZeroMemory(cab->next, sizeof(fdi_decomp_state));
2078 /* copy pszCabPath to userpath */
2079 ZeroMemory(userpath, 256);
2080 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2082 if (pathlen < 256) {
2083 for (i = 0; i <= pathlen; i++)
2084 userpath[i] = pszCabPath[i];
2085 } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2088 /* initial fdintNEXT_CABINET notification */
2089 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2090 fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
2091 fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
2092 fdin.psz3 = &userpath[0];
2093 fdin.fdie = FDIERROR_NONE;
2096 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2100 pathlen = strlen(userpath);
2101 filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
2103 /* slight overestimation here to save CPU cycles in the developer's brain */
2104 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2105 ERR("MAX_PATH exceeded.\n");
2106 return DECR_ILLEGALDATA;
2109 /* paste the path and filename together */
2112 for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
2113 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2115 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
2116 fullpath[idx] = '\0';
2118 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2120 /* try to get a handle to the cabfile */
2121 cabhf = PFDI_OPEN(CAB(hfdi), fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2123 /* no file. allow the user to try again */
2124 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2125 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2130 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2131 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2132 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2136 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2137 if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
2138 WARN("FDIIsCabinet failed.\n");
2139 PFDI_CLOSE(CAB(hfdi), cabhf);
2140 fdin.fdie = FDIERROR_NOT_A_CABINET;
2141 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2145 if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
2146 WARN("Wrong Cabinet.\n");
2147 PFDI_CLOSE(CAB(hfdi), cabhf);
2148 fdin.fdie = FDIERROR_WRONG_CABINET;
2149 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2157 /* cabinet notification */
2158 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2159 fdin.setID = fdici.setID;
2160 fdin.iCabinet = fdici.iCabinet;
2162 fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2163 fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2164 fdin.psz3 = pszCabPath;
2166 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2168 cab->next->setID = fdici.setID;
2169 cab->next->iCabinet = fdici.iCabinet;
2170 cab->next->hfdi = CAB(hfdi);
2171 cab->next->filehf = CAB(filehf);
2172 cab->next->cabhf = cabhf;
2173 cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2175 cab = cab->next; /* advance to the next cabinet */
2178 for (i = 0; i < fdici.cFolders; i++) {
2179 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF)
2182 if (cab->mii.folder_resv > 0)
2183 PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2185 fol = PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2187 ERR("out of memory!\n");
2188 return DECR_NOMEMORY;
2190 ZeroMemory(fol, sizeof(struct fdi_folder));
2191 if (!(cab->firstfol)) cab->firstfol = fol;
2193 fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2194 fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2195 fol->comp_type = EndGetI16(buf2+cffold_CompType);
2198 linkfol->next = fol;
2203 for (i = 0; i < fdici.cFiles; i++) {
2204 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2207 file = PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2209 ERR("out of memory!\n");
2210 return DECR_NOMEMORY;
2212 ZeroMemory(file, sizeof(struct fdi_file));
2213 if (!(cab->firstfile)) cab->firstfile = file;
2215 file->length = EndGetI32(buf2+cffile_UncompressedSize);
2216 file->offset = EndGetI32(buf2+cffile_FolderOffset);
2217 file->index = EndGetI16(buf2+cffile_FolderIndex);
2218 file->time = EndGetI16(buf2+cffile_Time);
2219 file->date = EndGetI16(buf2+cffile_Date);
2220 file->attribs = EndGetI16(buf2+cffile_Attribs);
2221 file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2223 if (!file->filename) return DECR_INPUT;
2226 linkfile->next = file;
2231 cab = cab->next; /* advance to the next cabinet */
2233 /* iterate files -- if we encounter the continued file, process it --
2234 otherwise, jump to the label above and keep looking */
2236 for (file = cab->firstfile; (file); file = file->next) {
2237 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2238 /* check to ensure a real match */
2239 if (lstrcmpiA(fi->filename, file->filename) == 0) {
2241 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2247 if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2248 "Wrong Cabinet" notification? */
2252 /* decompress block */
2253 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2255 CAB(outlen) = outlen;
2256 CAB(outpos) = CAB(outbuf);
2259 CAB(decomp_cab) = cab;
2263 static void free_decompression_temps(HFDI hfdi, const struct fdi_folder *fol,
2264 fdi_decomp_state *decomp_state)
2266 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2267 case cffoldCOMPTYPE_LZX:
2269 PFDI_FREE(hfdi, LZX(window));
2273 case cffoldCOMPTYPE_QUANTUM:
2275 PFDI_FREE(hfdi, QTM(window));
2282 static void free_decompression_mem(HFDI hfdi,
2283 fdi_decomp_state *decomp_state, struct fdi_file *file)
2285 struct fdi_folder *fol;
2286 while (decomp_state) {
2287 fdi_decomp_state *prev_fds;
2289 PFDI_CLOSE(hfdi, CAB(cabhf));
2291 /* free the storage remembered by mii */
2292 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2293 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2294 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2295 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2297 while (CAB(firstfol)) {
2298 fol = CAB(firstfol);
2299 CAB(firstfol) = CAB(firstfol)->next;
2300 PFDI_FREE(hfdi, fol);
2302 while (CAB(firstfile)) {
2303 file = CAB(firstfile);
2304 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2305 CAB(firstfile) = CAB(firstfile)->next;
2306 PFDI_FREE(hfdi, file);
2308 prev_fds = decomp_state;
2309 decomp_state = CAB(next);
2310 PFDI_FREE(hfdi, prev_fds);
2314 /***********************************************************************
2315 * FDICopy (CABINET.22)
2317 * Iterates through the files in the Cabinet file indicated by name and
2318 * file-location. May chain forward to additional cabinets (typically
2319 * only one) if files which begin in this Cabinet are continued in another
2320 * cabinet. For each file which is partially contained in this cabinet,
2321 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2322 * notification to the pfnfdin callback. For each file which begins in
2323 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2324 * callback, and the file is optionally decompressed and saved to disk.
2325 * Notification is not provided for files which are not at least partially
2326 * contained in the specified cabinet file.
2328 * See below for a thorough explanation of the various notification
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
2339 * pvUser [I] arbitrary void * value which is passed to callbacks.
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).
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.
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.
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.
2478 BOOL __cdecl FDICopy(
2483 PFNFDINOTIFY pfnfdin,
2484 PFNFDIDECRYPT pfnfdid,
2487 FDICABINETINFO fdici;
2488 FDINOTIFICATION fdin;
2489 INT_PTR cabhf, filehf = 0;
2492 char fullpath[MAX_PATH];
2493 size_t pathlen, filenamelen;
2494 char emptystring = '\0';
2496 struct fdi_folder *fol = NULL, *linkfol = NULL;
2497 struct fdi_file *file = NULL, *linkfile = NULL;
2498 fdi_decomp_state *decomp_state;
2500 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, "
2501 "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2502 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2504 if (!REALLY_IS_FDI(hfdi)) {
2505 SetLastError(ERROR_INVALID_HANDLE);
2509 if (!(decomp_state = PFDI_ALLOC(hfdi, sizeof(fdi_decomp_state))))
2511 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2514 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2516 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2517 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2519 /* slight overestimation here to save CPU cycles in the developer's brain */
2520 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2521 ERR("MAX_PATH exceeded.\n");
2522 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2523 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2524 PFDI_INT(hfdi)->perf->fError = TRUE;
2525 SetLastError(ERROR_FILE_NOT_FOUND);
2529 /* paste the path and filename together */
2532 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2533 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2535 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2536 fullpath[idx] = '\0';
2538 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2540 /* get a handle to the cabfile */
2541 cabhf = PFDI_OPEN(hfdi, fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2543 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2544 PFDI_INT(hfdi)->perf->fError = TRUE;
2545 SetLastError(ERROR_FILE_NOT_FOUND);
2550 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2551 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2552 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2553 PFDI_INT(hfdi)->perf->fError = TRUE;
2554 SetLastError(ERROR_FILE_NOT_FOUND);
2558 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2559 if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2560 ERR("FDIIsCabinet failed.\n");
2561 PFDI_CLOSE(hfdi, cabhf);
2565 /* cabinet notification */
2566 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2567 fdin.setID = fdici.setID;
2568 fdin.iCabinet = fdici.iCabinet;
2570 fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2571 fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2572 fdin.psz3 = pszCabPath;
2574 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2575 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2576 PFDI_INT(hfdi)->perf->erfType = 0;
2577 PFDI_INT(hfdi)->perf->fError = TRUE;
2581 CAB(setID) = fdici.setID;
2582 CAB(iCabinet) = fdici.iCabinet;
2586 for (i = 0; i < fdici.cFolders; i++) {
2587 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2588 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2589 PFDI_INT(hfdi)->perf->erfType = 0;
2590 PFDI_INT(hfdi)->perf->fError = TRUE;
2594 if (CAB(mii).folder_resv > 0)
2595 PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2597 fol = PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2599 ERR("out of memory!\n");
2600 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2601 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2602 PFDI_INT(hfdi)->perf->fError = TRUE;
2603 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2606 ZeroMemory(fol, sizeof(struct fdi_folder));
2607 if (!CAB(firstfol)) CAB(firstfol) = fol;
2609 fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2610 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2611 fol->comp_type = EndGetI16(buf+cffold_CompType);
2614 linkfol->next = fol;
2619 for (i = 0; i < fdici.cFiles; i++) {
2620 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2621 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2622 PFDI_INT(hfdi)->perf->erfType = 0;
2623 PFDI_INT(hfdi)->perf->fError = TRUE;
2627 file = PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2629 ERR("out of memory!\n");
2630 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2631 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2632 PFDI_INT(hfdi)->perf->fError = TRUE;
2633 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2636 ZeroMemory(file, sizeof(struct fdi_file));
2637 if (!CAB(firstfile)) CAB(firstfile) = file;
2639 file->length = EndGetI32(buf+cffile_UncompressedSize);
2640 file->offset = EndGetI32(buf+cffile_FolderOffset);
2641 file->index = EndGetI16(buf+cffile_FolderIndex);
2642 file->time = EndGetI16(buf+cffile_Time);
2643 file->date = EndGetI16(buf+cffile_Date);
2644 file->attribs = EndGetI16(buf+cffile_Attribs);
2645 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2647 if (!file->filename) {
2648 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2649 PFDI_INT(hfdi)->perf->erfType = 0;
2650 PFDI_INT(hfdi)->perf->fError = TRUE;
2655 linkfile->next = file;
2659 for (file = CAB(firstfile); (file); file = file->next) {
2662 * FIXME: This implementation keeps multiple cabinet files open at once
2663 * when encountering a split cabinet. It is a quirk of this implementation
2664 * that sometimes we decrypt the same block of data more than once, to find
2665 * the right starting point for a file, moving the file-pointer backwards.
2666 * If we kept a cache of certain file-pointer information, we could eliminate
2667 * that behavior... in fact I am not sure that the caching we already have
2668 * is not sufficient.
2670 * The current implementation seems to work fine in straightforward situations
2671 * where all the cabinet files needed for decryption are simultaneously
2672 * available. But presumably, the API is supposed to support cabinets which
2673 * are split across multiple CDROMS; we may need to change our implementation
2674 * to strictly serialize it's file usage so that it opens only one cabinet
2675 * at a time. Some experimentation with Windows is needed to figure out the
2676 * precise semantics required. The relevant code is here and in fdi_decomp().
2679 /* partial-file notification */
2680 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2682 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2683 * and perform some tests to figure out the right behavior. The SDK says
2684 * FDICopy will notify the user of the filename and "disk name" (info) of
2685 * the cabinet where the spanning file /started/.
2687 * That would certainly be convenient for the API-user, who could abort,
2688 * everything (or parallelize, if that's allowed (it is in wine)), and call
2689 * FDICopy again with the provided filename, so as to avoid partial file
2690 * notification and successfully unpack. This task could be quite unpleasant
2691 * from wine's perspective: the information specifying the "start cabinet" for
2692 * a file is associated nowhere with the file header and is not to be found in
2693 * the cabinet header. We have only the index of the cabinet wherein the folder
2694 * begins, which contains the file. To find that cabinet, we must consider the
2695 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2696 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2699 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2700 * cabinet other than the active one might be at another filepath than the
2701 * current one, or on another CDROM. This could get rather dicey, especially
2702 * if we imagine parallelized access to the FDICopy API.
2704 * The current implementation punts -- it just returns the previous cabinet and
2705 * it's info from the header of this cabinet. This provides the right answer in
2706 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2709 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2711 fdin.psz1 = (char *)file->filename;
2712 fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2713 fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2715 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2716 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2717 PFDI_INT(hfdi)->perf->erfType = 0;
2718 PFDI_INT(hfdi)->perf->fError = TRUE;
2721 /* I don't think we are supposed to decompress partial files. This prevents it. */
2722 file->oppressed = TRUE;
2724 if (file->oppressed) {
2727 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2729 fdin.psz1 = (char *)file->filename;
2730 fdin.cb = file->length;
2731 fdin.date = file->date;
2732 fdin.time = file->time;
2733 fdin.attribs = file->attribs;
2734 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2735 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2736 PFDI_INT(hfdi)->perf->erfType = 0;
2737 PFDI_INT(hfdi)->perf->fError = TRUE;
2743 /* find the folder for this file if necc. */
2747 fol = CAB(firstfol);
2748 if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2749 /* pick the last folder */
2750 while (fol->next) fol = fol->next;
2752 for (i2 = 0; (i2 < file->index); i2++)
2753 if (fol->next) /* bug resistance, should always be true */
2759 cab_UWORD comptype = fol->comp_type;
2760 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2761 int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2764 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2766 /* set up decomp_state */
2768 CAB(filehf) = filehf;
2770 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2771 if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2773 TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2775 /* free stuff for the old decompresser */
2777 case cffoldCOMPTYPE_LZX:
2779 PFDI_FREE(hfdi, LZX(window));
2783 case cffoldCOMPTYPE_QUANTUM:
2785 PFDI_FREE(hfdi, QTM(window));
2791 CAB(decomp_cab) = NULL;
2792 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2796 /* initialize the new decompresser */
2798 case cffoldCOMPTYPE_NONE:
2799 CAB(decompress) = NONEfdi_decomp;
2801 case cffoldCOMPTYPE_MSZIP:
2802 CAB(decompress) = ZIPfdi_decomp;
2804 case cffoldCOMPTYPE_QUANTUM:
2805 CAB(decompress) = QTMfdi_decomp;
2806 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2808 case cffoldCOMPTYPE_LZX:
2809 CAB(decompress) = LZXfdi_decomp;
2810 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2813 err = DECR_DATAFORMAT;
2823 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2824 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2825 PFDI_INT(hfdi)->perf->fError = TRUE;
2826 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2829 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2830 PFDI_INT(hfdi)->perf->erfOper = 0;
2831 PFDI_INT(hfdi)->perf->fError = TRUE;
2835 if (file->offset > CAB(offset)) {
2836 /* decode bytes and send them to /dev/null */
2837 switch (fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser)) {
2840 case DECR_USERABORT:
2841 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2842 PFDI_INT(hfdi)->perf->erfType = 0;
2843 PFDI_INT(hfdi)->perf->fError = TRUE;
2846 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2847 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2848 PFDI_INT(hfdi)->perf->fError = TRUE;
2849 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2852 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2853 PFDI_INT(hfdi)->perf->erfOper = 0;
2854 PFDI_INT(hfdi)->perf->fError = TRUE;
2857 CAB(offset) = file->offset;
2860 /* now do the actual decompression */
2861 err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2862 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2864 /* fdintCLOSE_FILE_INFO notification */
2865 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2867 fdin.psz1 = (char *)file->filename;
2869 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2870 fdin.date = file->date;
2871 fdin.time = file->time;
2872 fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2873 ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2879 case DECR_USERABORT:
2880 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2881 PFDI_INT(hfdi)->perf->erfType = 0;
2882 PFDI_INT(hfdi)->perf->fError = TRUE;
2885 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2886 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2887 PFDI_INT(hfdi)->perf->fError = TRUE;
2888 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2891 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2892 PFDI_INT(hfdi)->perf->erfOper = 0;
2893 PFDI_INT(hfdi)->perf->fError = TRUE;
2899 free_decompression_temps(hfdi, fol, decomp_state);
2900 free_decompression_mem(hfdi, decomp_state, file);
2904 bail_and_fail: /* here we free ram before error returns */
2906 if (fol) free_decompression_temps(hfdi, fol, decomp_state);
2908 if (filehf) PFDI_CLOSE(hfdi, filehf);
2910 free_decompression_mem(hfdi, decomp_state, file);
2915 /***********************************************************************
2916 * FDIDestroy (CABINET.23)
2918 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2919 * of FDICopy. Only reason for failure would be an invalid handle.
2922 * hfdi [I] The HFDI to free
2928 BOOL __cdecl FDIDestroy(HFDI hfdi)
2930 TRACE("(hfdi == ^%p)\n", hfdi);
2931 if (REALLY_IS_FDI(hfdi)) {
2932 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2933 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2936 SetLastError(ERROR_INVALID_HANDLE);
2941 /***********************************************************************
2942 * FDITruncateCabinet (CABINET.24)
2944 * Removes all folders of a cabinet file after and including the
2945 * specified folder number.
2948 * hfdi [I] Handle to the FDI context.
2949 * pszCabinetName [I] Filename of the cabinet.
2950 * iFolderToDelete [I] Index of the first folder to delete.
2957 * The PFNWRITE function supplied to FDICreate must truncate the
2958 * file at the current position if the number of bytes to write is 0.
2960 BOOL __cdecl FDITruncateCabinet(
2962 char *pszCabinetName,
2963 USHORT iFolderToDelete)
2965 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2966 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2968 if (!REALLY_IS_FDI(hfdi)) {
2969 SetLastError(ERROR_INVALID_HANDLE);
2973 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);