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 = (*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_read_string (internal)
417 * allocate and read an arbitrarily long string from the cabinet
419 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
422 base = FDI_getoffset(hfdi, hf),
423 maxlen = cabsize - base;
426 cab_UBYTE *buf = NULL;
428 TRACE("(hfdi == ^%p, hf == %ld, cabsize == %ld)\n", hfdi, hf, cabsize);
431 if (len > maxlen) len = maxlen;
432 if (!(buf = PFDI_ALLOC(hfdi, len))) break;
433 if (!PFDI_READ(hfdi, hf, buf, len)) break;
435 /* search for a null terminator in what we've just read */
436 for (i=0; i < len; i++) {
437 if (!buf[i]) {ok=TRUE; break;}
442 ERR("cabinet is truncated\n");
445 /* The buffer is too small for the string. Reset the file to the point
446 * were we started, free the buffer and increase the size for the next try
448 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
449 PFDI_FREE(hfdi, buf);
457 PFDI_FREE(hfdi, buf);
459 ERR("out of memory!\n");
463 /* otherwise, set the stream to just after the string and return */
464 PFDI_SEEK(hfdi, hf, base + strlen((char *)buf) + 1, SEEK_SET);
469 /******************************************************************
470 * FDI_read_entries (internal)
472 * process the cabinet header in the style of FDIIsCabinet, but
473 * without the sanity checks (and bug)
475 static BOOL FDI_read_entries(
478 PFDICABINETINFO pfdici,
479 PMORE_ISCAB_INFO pmii)
481 int num_folders, num_files, header_resv, folder_resv = 0;
482 LONG base_offset, cabsize;
483 USHORT setid, cabidx, flags;
484 cab_UBYTE buf[64], block_resv;
485 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
487 TRACE("(hfdi == ^%p, hf == %ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
490 * FIXME: I just noticed that I am memorizing the initial file pointer
491 * offset and restoring it before reading in the rest of the header
492 * information in the cabinet. Perhaps that's correct -- that is, perhaps
493 * this API is supposed to support "streaming" cabinets which are embedded
494 * in other files, or cabinets which begin at file offsets other than zero.
495 * Otherwise, I should instead go to the absolute beginning of the file.
496 * (Either way, the semantics of wine's FDICopy require me to leave the
497 * file pointer where it is afterwards -- If Windows does not do so, we
498 * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
500 * So, the answer lies in Windows; will native cabinet.dll recognize a
501 * cabinet "file" embedded in another file? Note that cabextract.c does
502 * support this, which implies that Microsoft's might. I haven't tried it
503 * yet so I don't know. ATM, most of wine's FDI cabinet routines (except
504 * this one) would not work in this way. To fix it, we could just make the
505 * various references to absolute file positions in the code relative to an
506 * initial "beginning" offset. Because the FDICopy API doesn't take a
507 * file-handle like this one, we would therein need to search through the
508 * file for the beginning of the cabinet (as we also do in cabextract.c).
509 * Note that this limits us to a maximum of one cabinet per. file: the first.
511 * So, in summary: either the code below is wrong, or the rest of fdi.c is
512 * wrong... I cannot imagine that both are correct ;) One of these flaws
513 * should be fixed after determining the behavior on Windows. We ought
514 * to check both FDIIsCabinet and FDICopy for the right behavior.
519 /* get basic offset & size info */
520 base_offset = FDI_getoffset(hfdi, hf);
522 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
524 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
525 PFDI_INT(hfdi)->perf->erfType = 0;
526 PFDI_INT(hfdi)->perf->fError = TRUE;
531 cabsize = FDI_getoffset(hfdi, hf);
533 if ((cabsize == -1) || (base_offset == -1) ||
534 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
536 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
537 PFDI_INT(hfdi)->perf->erfType = 0;
538 PFDI_INT(hfdi)->perf->fError = TRUE;
543 /* read in the CFHEADER */
544 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
546 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
547 PFDI_INT(hfdi)->perf->erfType = 0;
548 PFDI_INT(hfdi)->perf->fError = TRUE;
553 /* check basic MSCF signature */
554 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
556 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
557 PFDI_INT(hfdi)->perf->erfType = 0;
558 PFDI_INT(hfdi)->perf->fError = TRUE;
563 /* get the number of folders */
564 num_folders = EndGetI16(buf+cfhead_NumFolders);
565 if (num_folders == 0) {
566 /* PONDERME: is this really invalid? */
567 WARN("weird cabinet detect failure: no folders in cabinet\n");
569 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
570 PFDI_INT(hfdi)->perf->erfType = 0;
571 PFDI_INT(hfdi)->perf->fError = TRUE;
576 /* get the number of files */
577 num_files = EndGetI16(buf+cfhead_NumFiles);
578 if (num_files == 0) {
579 /* PONDERME: is this really invalid? */
580 WARN("weird cabinet detect failure: no files in cabinet\n");
582 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
583 PFDI_INT(hfdi)->perf->erfType = 0;
584 PFDI_INT(hfdi)->perf->fError = TRUE;
590 setid = EndGetI16(buf+cfhead_SetID);
592 /* cabinet (set) index */
593 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
595 /* check the header revision */
596 if ((buf[cfhead_MajorVersion] > 1) ||
597 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
599 WARN("cabinet format version > 1.3\n");
601 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
602 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
603 PFDI_INT(hfdi)->perf->fError = TRUE;
608 /* pull the flags out */
609 flags = EndGetI16(buf+cfhead_Flags);
611 /* read the reserved-sizes part of header, if present */
612 if (flags & cfheadRESERVE_PRESENT) {
613 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
614 ERR("bunk reserve-sizes?\n");
616 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
617 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
618 PFDI_INT(hfdi)->perf->fError = TRUE;
623 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
624 if (pmii) pmii->header_resv = header_resv;
625 folder_resv = buf[cfheadext_FolderReserved];
626 if (pmii) pmii->folder_resv = folder_resv;
627 block_resv = buf[cfheadext_DataReserved];
628 if (pmii) pmii->block_resv = block_resv;
630 if (header_resv > 60000) {
631 WARN("WARNING; header reserved space > 60000\n");
634 /* skip the reserved header */
635 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
636 ERR("seek failure: header_resv\n");
638 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
639 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
640 PFDI_INT(hfdi)->perf->fError = TRUE;
646 if (flags & cfheadPREV_CABINET) {
647 prevname = FDI_read_string(hfdi, hf, cabsize);
650 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
651 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
652 PFDI_INT(hfdi)->perf->fError = TRUE;
657 pmii->prevname = prevname;
659 PFDI_FREE(hfdi, prevname);
660 previnfo = FDI_read_string(hfdi, hf, cabsize);
663 pmii->previnfo = previnfo;
665 PFDI_FREE(hfdi, previnfo);
669 if (flags & cfheadNEXT_CABINET) {
671 pmii->hasnext = TRUE;
672 nextname = FDI_read_string(hfdi, hf, cabsize);
674 if ((flags & cfheadPREV_CABINET) && pmii) {
675 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
676 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
678 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
679 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
680 PFDI_INT(hfdi)->perf->fError = TRUE;
684 pmii->nextname = nextname;
686 PFDI_FREE(hfdi, nextname);
687 nextinfo = FDI_read_string(hfdi, hf, cabsize);
690 pmii->nextinfo = nextinfo;
692 PFDI_FREE(hfdi, nextinfo);
696 /* we could process the whole cabinet searching for problems;
697 instead lets stop here. Now let's fill out the paperwork */
698 pfdici->cbCabinet = cabsize;
699 pfdici->cFolders = num_folders;
700 pfdici->cFiles = num_files;
701 pfdici->setID = setid;
702 pfdici->iCabinet = cabidx;
703 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
704 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
705 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
709 /***********************************************************************
710 * FDIIsCabinet (CABINET.21)
712 * Informs the caller as to whether or not the provided file handle is
713 * really a cabinet or not, filling out the provided PFDICABINETINFO
714 * structure with information about the cabinet. Brief explanations of
715 * the elements of this structure are available as comments accompanying
716 * its definition in wine's include/fdi.h.
719 * hfdi [I] An HFDI from FDICreate
720 * hf [I] The file handle about which the caller inquires
721 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
722 * be filled out with information about the cabinet
723 * file indicated by hf if, indeed, it is determined
727 * TRUE if the file is a cabinet. The info pointed to by pfdici will
729 * FALSE if the file is not a cabinet, or if an error was encountered
730 * while processing the cabinet. The PERF structure provided to
731 * FDICreate can be queried for more error information.
736 BOOL __cdecl FDIIsCabinet(
739 PFDICABINETINFO pfdici)
743 TRACE("(hfdi == ^%p, hf == ^%ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
745 if (!REALLY_IS_FDI(hfdi)) {
746 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
747 SetLastError(ERROR_INVALID_HANDLE);
753 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
754 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
755 PFDI_INT(hfdi)->perf->fError = TRUE; */
756 SetLastError(ERROR_INVALID_HANDLE);
762 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
763 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
764 PFDI_INT(hfdi)->perf->fError = TRUE; */
765 SetLastError(ERROR_BAD_ARGUMENTS);
768 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
771 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
776 /******************************************************************
777 * QTMfdi_initmodel (internal)
779 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
781 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
786 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
787 for (i = 0; i < n; i++) {
788 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
789 m->syms[i].sym = i+s; /* actual symbol */
790 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
792 m->syms[n].cumfreq = 0;
795 /******************************************************************
796 * QTMfdi_init (internal)
798 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
799 unsigned int wndsize = 1 << window;
800 int msz = window * 2, i;
803 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
804 /* if a previously allocated window is big enough, keep it */
805 if (window < 10 || window > 21) return DECR_DATAFORMAT;
806 if (QTM(actual_size) < wndsize) {
807 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
811 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
812 QTM(actual_size) = wndsize;
814 QTM(window_size) = wndsize;
815 QTM(window_posn) = 0;
817 /* initialize static slot/extrabits tables */
818 for (i = 0, j = 0; i < 27; i++) {
819 CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
820 CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
822 for (i = 0, j = 0; i < 42; i++) {
823 CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
824 CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
827 /* initialize arithmetic coding models */
829 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
831 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
832 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
833 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
834 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
836 /* model 4 depends on table size, ranges from 20 to 24 */
837 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
838 /* model 5 depends on table size, ranges from 20 to 36 */
839 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
840 /* model 6pos depends on table size, ranges from 20 to 42 */
841 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
842 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
847 /************************************************************
848 * LZXfdi_init (internal)
850 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
851 static const cab_UBYTE bits[] =
852 { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
853 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
854 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
856 static const cab_ULONG base[] =
857 { 0, 1, 2, 3, 4, 6, 8, 12,
858 16, 24, 32, 48, 64, 96, 128, 192,
859 256, 384, 512, 768, 1024, 1536, 2048, 3072,
860 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
861 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
862 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
863 1835008, 1966080, 2097152};
864 cab_ULONG wndsize = 1 << window;
867 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
868 /* if a previously allocated window is big enough, keep it */
869 if (window < 15 || window > 21) return DECR_DATAFORMAT;
870 if (LZX(actual_size) < wndsize) {
871 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
875 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
876 LZX(actual_size) = wndsize;
878 LZX(window_size) = wndsize;
880 /* initialize static tables */
881 memcpy(CAB(extra_bits), bits, sizeof(bits));
882 memcpy(CAB(lzx_position_base), base, sizeof(base));
884 /* calculate required position slots */
885 if (window == 20) posn_slots = 42;
886 else if (window == 21) posn_slots = 50;
887 else posn_slots = window << 1;
889 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
891 LZX(R0) = LZX(R1) = LZX(R2) = 1;
892 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
893 LZX(header_read) = 0;
894 LZX(frames_read) = 0;
895 LZX(block_remaining) = 0;
896 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
897 LZX(intel_curpos) = 0;
898 LZX(intel_started) = 0;
899 LZX(window_posn) = 0;
901 /* initialize tables to 0 (because deltas will be applied to them) */
902 memset(LZX(MAINTREE_len), 0, sizeof(LZX(MAINTREE_len)));
903 memset(LZX(LENGTH_len), 0, sizeof(LZX(LENGTH_len)));
908 /****************************************************
909 * NONEfdi_decomp(internal)
911 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
913 if (inlen != outlen) return DECR_ILLEGALDATA;
914 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
918 /********************************************************
919 * Ziphuft_free (internal)
921 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
923 register struct Ziphuft *p, *q;
925 /* Go through linked list, freeing from the allocated (t[-1]) address. */
927 while (p != (struct Ziphuft *)NULL)
935 /*********************************************************
936 * fdi_Ziphuft_build (internal)
938 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, const cab_UWORD *d, const cab_UWORD *e,
939 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
941 cab_ULONG a; /* counter for codes of length k */
942 cab_ULONG el; /* length of EOB code (value 256) */
943 cab_ULONG f; /* i repeats in table every f entries */
944 cab_LONG g; /* maximum code length */
945 cab_LONG h; /* table level */
946 register cab_ULONG i; /* counter, current code */
947 register cab_ULONG j; /* counter */
948 register cab_LONG k; /* number of bits in current code */
949 cab_LONG *l; /* stack of bits per table */
950 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
951 register struct Ziphuft *q; /* points to current table */
952 struct Ziphuft r; /* table entry for structure assignment */
953 register cab_LONG w; /* bits before this table == (l * h) */
954 cab_ULONG *xp; /* pointer into x */
955 cab_LONG y; /* number of dummy codes added */
956 cab_ULONG z; /* number of entries in current table */
960 /* Generate counts for each bit length */
961 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
963 for(i = 0; i < ZIPBMAX+1; ++i)
968 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
970 if (ZIP(c)[0] == n) /* null input--all zero length codes */
972 *t = (struct Ziphuft *)NULL;
977 /* Find minimum and maximum length, bound *m by those */
978 for (j = 1; j <= ZIPBMAX; j++)
981 k = j; /* minimum code length */
982 if ((cab_ULONG)*m < j)
984 for (i = ZIPBMAX; i; i--)
987 g = i; /* maximum code length */
988 if ((cab_ULONG)*m > i)
991 /* Adjust last length count to fill out codes, if needed */
992 for (y = 1 << j; j < i; j++, y <<= 1)
993 if ((y -= ZIP(c)[j]) < 0)
994 return 2; /* bad input: more codes than bits */
995 if ((y -= ZIP(c)[i]) < 0)
999 /* Generate starting offsets LONGo the value table for each length */
1001 p = ZIP(c) + 1; xp = ZIP(x) + 2;
1003 { /* note that i == g from above */
1004 *xp++ = (j += *p++);
1007 /* Make a table of values in order of bit lengths */
1010 if ((j = *p++) != 0)
1011 ZIP(v)[ZIP(x)[j]++] = i;
1015 /* Generate the Huffman codes and for each, make the table entries */
1016 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
1017 p = ZIP(v); /* grab values in bit order */
1018 h = -1; /* no tables yet--level -1 */
1019 w = l[-1] = 0; /* no bits decoded yet */
1020 ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */
1021 q = (struct Ziphuft *)NULL; /* ditto */
1024 /* go through the bit lengths (k already is bits in shortest code) */
1030 /* here i is the Huffman code of length k bits for value *p */
1031 /* make tables up to required level */
1032 while (k > w + l[h])
1034 w += l[h++]; /* add bits already decoded */
1036 /* compute minimum size table less than or equal to *m bits */
1037 z = (z = g - w) > (cab_ULONG)*m ? *m : z; /* upper limit */
1038 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
1039 { /* too few codes for k-w bit table */
1040 f -= a + 1; /* deduct codes from patterns left */
1042 while (++j < z) /* try smaller tables up to z bits */
1044 if ((f <<= 1) <= *++xp)
1045 break; /* enough codes to use up j bits */
1046 f -= *xp; /* else deduct codes from patterns */
1049 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
1050 j = el - w; /* make EOB code end at table */
1051 z = 1 << j; /* table entries for j-bit table */
1052 l[h] = j; /* set table size in stack */
1054 /* allocate and link in new table */
1055 if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
1058 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
1059 return 3; /* not enough memory */
1061 *t = q + 1; /* link to list for Ziphuft_free() */
1062 *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
1063 ZIP(u)[h] = ++q; /* table starts after link */
1065 /* connect to last table, if there is one */
1068 ZIP(x)[h] = i; /* save pattern for backing up */
1069 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
1070 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
1071 r.v.t = q; /* pointer to this table */
1072 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
1073 ZIP(u)[h-1][j] = r; /* connect to last table */
1077 /* set up table entry in r */
1078 r.b = (cab_UBYTE)(k - w);
1079 if (p >= ZIP(v) + n)
1080 r.e = 99; /* out of values--invalid code */
1083 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
1084 r.v.n = *p++; /* simple code is just the value */
1088 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
1089 r.v.n = d[*p++ - s];
1092 /* fill code-like entries with r */
1094 for (j = i >> w; j < z; j += f)
1097 /* backwards increment the k-bit code i */
1098 for (j = 1 << (k - 1); i & j; j >>= 1)
1102 /* backup over finished tables */
1103 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
1104 w -= l[--h]; /* don't need to update q */
1108 /* return actual size of base table */
1111 /* Return true (1) if we were given an incomplete table */
1112 return y != 0 && g != 1;
1115 /*********************************************************
1116 * fdi_Zipinflate_codes (internal)
1118 static cab_LONG fdi_Zipinflate_codes(const struct Ziphuft *tl, const struct Ziphuft *td,
1119 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
1121 register cab_ULONG e; /* table entry flag/number of extra bits */
1122 cab_ULONG n, d; /* length and index for copy */
1123 cab_ULONG w; /* current window position */
1124 const struct Ziphuft *t; /* pointer to table entry */
1125 cab_ULONG ml, md; /* masks for bl and bd bits */
1126 register cab_ULONG b; /* bit buffer */
1127 register cab_ULONG k; /* number of bits in bit buffer */
1129 /* make local copies of globals */
1130 b = ZIP(bb); /* initialize bit buffer */
1132 w = ZIP(window_posn); /* initialize window position */
1134 /* inflate the coded data */
1135 ml = Zipmask[bl]; /* precompute masks for speed */
1140 ZIPNEEDBITS((cab_ULONG)bl)
1141 if((e = (t = tl + (b & ml))->e) > 16)
1149 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1151 if (e == 16) /* then it's a literal */
1152 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
1153 else /* it's an EOB or a length */
1155 /* exit if end of block */
1159 /* get length of block to copy */
1161 n = t->v.n + (b & Zipmask[e]);
1164 /* decode distance of block to copy */
1165 ZIPNEEDBITS((cab_ULONG)bd)
1166 if ((e = (t = td + (b & md))->e) > 16)
1173 } while ((e = (t = t->v.t + (b & Zipmask[e]))->e) > 16);
1176 d = w - t->v.n - (b & Zipmask[e]);
1180 n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
1183 CAB(outbuf)[w++] = CAB(outbuf)[d++];
1189 /* restore the globals from the locals */
1190 ZIP(window_posn) = w; /* restore global window pointer */
1191 ZIP(bb) = b; /* restore global bit buffer */
1198 /***********************************************************
1199 * Zipinflate_stored (internal)
1201 static cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1202 /* "decompress" an inflated type 0 (stored) block. */
1204 cab_ULONG n; /* number of bytes in block */
1205 cab_ULONG w; /* current window position */
1206 register cab_ULONG b; /* bit buffer */
1207 register cab_ULONG k; /* number of bits in bit buffer */
1209 /* make local copies of globals */
1210 b = ZIP(bb); /* initialize bit buffer */
1212 w = ZIP(window_posn); /* initialize window position */
1214 /* go to byte boundary */
1218 /* get the length and its complement */
1223 if (n != ((~b) & 0xffff))
1224 return 1; /* error in compressed data */
1227 /* read and output the compressed data */
1231 CAB(outbuf)[w++] = (cab_UBYTE)b;
1235 /* restore the globals from the locals */
1236 ZIP(window_posn) = w; /* restore global window pointer */
1237 ZIP(bb) = b; /* restore global bit buffer */
1242 /******************************************************
1243 * fdi_Zipinflate_fixed (internal)
1245 static cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1247 struct Ziphuft *fixed_tl;
1248 struct Ziphuft *fixed_td;
1249 cab_LONG fixed_bl, fixed_bd;
1250 cab_LONG i; /* temporary variable */
1256 for(i = 0; i < 144; i++)
1262 for(; i < 288; i++) /* make a complete, but wrong code set */
1265 if((i = fdi_Ziphuft_build(l, 288, 257, Zipcplens, Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1268 /* distance table */
1269 for(i = 0; i < 30; i++) /* make an incomplete code set */
1272 if((i = fdi_Ziphuft_build(l, 30, 0, Zipcpdist, Zipcpdext, &fixed_td, &fixed_bd, decomp_state)) > 1)
1274 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1278 /* decompress until an end-of-block code */
1279 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1281 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1282 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1286 /**************************************************************
1287 * fdi_Zipinflate_dynamic (internal)
1289 static cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1290 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1292 cab_LONG i; /* temporary variables */
1295 cab_ULONG l; /* last length */
1296 cab_ULONG m; /* mask for bit lengths table */
1297 cab_ULONG n; /* number of lengths to get */
1298 struct Ziphuft *tl; /* literal/length code table */
1299 struct Ziphuft *td; /* distance code table */
1300 cab_LONG bl; /* lookup bits for tl */
1301 cab_LONG bd; /* lookup bits for td */
1302 cab_ULONG nb; /* number of bit length codes */
1303 cab_ULONG nl; /* number of literal/length codes */
1304 cab_ULONG nd; /* number of distance codes */
1305 register cab_ULONG b; /* bit buffer */
1306 register cab_ULONG k; /* number of bits in bit buffer */
1308 /* make local bit buffer */
1313 /* read in table lengths */
1315 nl = 257 + (b & 0x1f); /* number of literal/length codes */
1318 nd = 1 + (b & 0x1f); /* number of distance codes */
1321 nb = 4 + (b & 0xf); /* number of bit length codes */
1323 if(nl > 288 || nd > 32)
1324 return 1; /* bad lengths */
1326 /* read in bit-length-code lengths */
1327 for(j = 0; j < nb; j++)
1330 ll[Zipborder[j]] = b & 7;
1334 ll[Zipborder[j]] = 0;
1336 /* build decoding table for trees--single level, 7 bit lookup */
1338 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1341 fdi_Ziphuft_free(CAB(hfdi), tl);
1342 return i; /* incomplete code set */
1345 /* read in literal and distance code lengths */
1349 while((cab_ULONG)i < n)
1351 ZIPNEEDBITS((cab_ULONG)bl)
1352 j = (td = tl + (b & m))->b;
1355 if (j < 16) /* length of code in bits (0..15) */
1356 ll[i++] = l = j; /* save last length in l */
1357 else if (j == 16) /* repeat last length 3 to 6 times */
1362 if((cab_ULONG)i + j > n)
1367 else if (j == 17) /* 3 to 10 zero length codes */
1372 if ((cab_ULONG)i + j > n)
1378 else /* j == 18: 11 to 138 zero length codes */
1381 j = 11 + (b & 0x7f);
1383 if ((cab_ULONG)i + j > n)
1391 /* free decoding table for trees */
1392 fdi_Ziphuft_free(CAB(hfdi), tl);
1394 /* restore the global bit buffer */
1398 /* build the decoding tables for literal/length and distance codes */
1400 if((i = fdi_Ziphuft_build(ll, nl, 257, Zipcplens, Zipcplext, &tl, &bl, decomp_state)) != 0)
1403 fdi_Ziphuft_free(CAB(hfdi), tl);
1404 return i; /* incomplete code set */
1407 fdi_Ziphuft_build(ll + nl, nd, 0, Zipcpdist, Zipcpdext, &td, &bd, decomp_state);
1409 /* decompress until an end-of-block code */
1410 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1413 /* free the decoding tables, return */
1414 fdi_Ziphuft_free(CAB(hfdi), tl);
1415 fdi_Ziphuft_free(CAB(hfdi), td);
1419 /*****************************************************
1420 * fdi_Zipinflate_block (internal)
1422 static cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1423 { /* decompress an inflated block */
1424 cab_ULONG t; /* block type */
1425 register cab_ULONG b; /* bit buffer */
1426 register cab_ULONG k; /* number of bits in bit buffer */
1428 /* make local bit buffer */
1432 /* read in last block bit */
1434 *e = (cab_LONG)b & 1;
1437 /* read in block type */
1442 /* restore the global bit buffer */
1446 /* inflate that block type */
1448 return fdi_Zipinflate_dynamic(decomp_state);
1450 return fdi_Zipinflate_stored(decomp_state);
1452 return fdi_Zipinflate_fixed(decomp_state);
1453 /* bad block type */
1457 /****************************************************
1458 * ZIPfdi_decomp(internal)
1460 static int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1462 cab_LONG e; /* last block flag */
1464 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1466 ZIP(inpos) = CAB(inbuf);
1467 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1468 if(outlen > ZIPWSIZE)
1469 return DECR_DATAFORMAT;
1471 /* CK = Chris Kirmse, official Microsoft purloiner */
1472 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1473 return DECR_ILLEGALDATA;
1477 if(fdi_Zipinflate_block(&e, decomp_state))
1478 return DECR_ILLEGALDATA;
1481 /* return success */
1485 /*******************************************************************
1486 * QTMfdi_decomp(internal)
1488 static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1490 cab_UBYTE *inpos = CAB(inbuf);
1491 cab_UBYTE *window = QTM(window);
1492 cab_UBYTE *runsrc, *rundest;
1493 cab_ULONG window_posn = QTM(window_posn);
1494 cab_ULONG window_size = QTM(window_size);
1496 /* used by bitstream macros */
1497 register int bitsleft, bitrun, bitsneed;
1498 register cab_ULONG bitbuf;
1500 /* used by GET_SYMBOL */
1505 int extra, togo = outlen, match_length = 0, copy_length;
1506 cab_UBYTE selector, sym;
1507 cab_ULONG match_offset = 0;
1509 cab_UWORD H = 0xFFFF, L = 0, C;
1511 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1513 /* read initial value of C */
1517 /* apply 2^x-1 mask */
1518 window_posn &= window_size - 1;
1519 /* runs can't straddle the window wraparound */
1520 if ((window_posn + togo) > window_size) {
1521 TRACE("straddled run\n");
1522 return DECR_DATAFORMAT;
1526 GET_SYMBOL(model7, selector);
1529 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1532 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1535 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1538 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1542 /* selector 4 = fixed length of 3 */
1543 GET_SYMBOL(model4, sym);
1544 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1545 match_offset = CAB(q_position_base)[sym] + extra + 1;
1550 /* selector 5 = fixed length of 4 */
1551 GET_SYMBOL(model5, sym);
1552 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1553 match_offset = CAB(q_position_base)[sym] + extra + 1;
1558 /* selector 6 = variable length */
1559 GET_SYMBOL(model6len, sym);
1560 Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1561 match_length = CAB(q_length_base)[sym] + extra + 5;
1562 GET_SYMBOL(model6pos, sym);
1563 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1564 match_offset = CAB(q_position_base)[sym] + extra + 1;
1568 TRACE("Selector is bogus\n");
1569 return DECR_ILLEGALDATA;
1572 /* if this is a match */
1573 if (selector >= 4) {
1574 rundest = window + window_posn;
1575 togo -= match_length;
1577 /* copy any wrapped around source data */
1578 if (window_posn >= match_offset) {
1580 runsrc = rundest - match_offset;
1582 runsrc = rundest + (window_size - match_offset);
1583 copy_length = match_offset - window_posn;
1584 if (copy_length < match_length) {
1585 match_length -= copy_length;
1586 window_posn += copy_length;
1587 while (copy_length-- > 0) *rundest++ = *runsrc++;
1591 window_posn += match_length;
1593 /* copy match data - no worries about destination wraps */
1594 while (match_length-- > 0) *rundest++ = *runsrc++;
1596 } /* while (togo > 0) */
1599 TRACE("Frame overflow, this_run = %d\n", togo);
1600 return DECR_ILLEGALDATA;
1603 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1606 QTM(window_posn) = window_posn;
1610 /************************************************************
1611 * fdi_lzx_read_lens (internal)
1613 static int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1614 fdi_decomp_state *decomp_state) {
1618 register cab_ULONG bitbuf = lb->bb;
1619 register int bitsleft = lb->bl;
1620 cab_UBYTE *inpos = lb->ip;
1623 for (x = 0; x < 20; x++) {
1625 LENTABLE(PRETREE)[x] = y;
1627 BUILD_TABLE(PRETREE);
1629 for (x = first; x < last; ) {
1630 READ_HUFFSYM(PRETREE, z);
1632 READ_BITS(y, 4); y += 4;
1633 while (y--) lens[x++] = 0;
1636 READ_BITS(y, 5); y += 20;
1637 while (y--) lens[x++] = 0;
1640 READ_BITS(y, 1); y += 4;
1641 READ_HUFFSYM(PRETREE, z);
1642 z = lens[x] - z; if (z < 0) z += 17;
1643 while (y--) lens[x++] = z;
1646 z = lens[x] - z; if (z < 0) z += 17;
1657 /*******************************************************
1658 * LZXfdi_decomp(internal)
1660 static int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1661 cab_UBYTE *inpos = CAB(inbuf);
1662 const cab_UBYTE *endinp = inpos + inlen;
1663 cab_UBYTE *window = LZX(window);
1664 cab_UBYTE *runsrc, *rundest;
1665 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1667 cab_ULONG window_posn = LZX(window_posn);
1668 cab_ULONG window_size = LZX(window_size);
1669 cab_ULONG R0 = LZX(R0);
1670 cab_ULONG R1 = LZX(R1);
1671 cab_ULONG R2 = LZX(R2);
1673 register cab_ULONG bitbuf;
1674 register int bitsleft;
1675 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1676 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1678 int togo = outlen, this_run, main_element, aligned_bits;
1679 int match_length, copy_length, length_footer, extra, verbatim_bits;
1681 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1685 /* read header if necessary */
1686 if (!LZX(header_read)) {
1688 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1689 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1690 LZX(header_read) = 1;
1693 /* main decoding loop */
1695 /* last block finished, new block expected */
1696 if (LZX(block_remaining) == 0) {
1697 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1698 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1702 READ_BITS(LZX(block_type), 3);
1705 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1707 switch (LZX(block_type)) {
1708 case LZX_BLOCKTYPE_ALIGNED:
1709 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1710 BUILD_TABLE(ALIGNED);
1711 /* rest of aligned header is same as verbatim */
1713 case LZX_BLOCKTYPE_VERBATIM:
1714 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1715 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1716 BUILD_TABLE(MAINTREE);
1717 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1719 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1720 BUILD_TABLE(LENGTH);
1723 case LZX_BLOCKTYPE_UNCOMPRESSED:
1724 LZX(intel_started) = 1; /* because we can't assume otherwise */
1725 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1726 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1727 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1728 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1729 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1733 return DECR_ILLEGALDATA;
1737 /* buffer exhaustion check */
1738 if (inpos > endinp) {
1739 /* it's possible to have a file where the next run is less than
1740 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1741 * in building the tables will exhaust the buffer, so we should
1742 * allow for this, but not allow those accidentally read bits to
1743 * be used (so we check that there are at least 16 bits
1744 * remaining - in this boundary case they aren't really part of
1745 * the compressed data)
1747 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1750 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1751 if (this_run > togo) this_run = togo;
1753 LZX(block_remaining) -= this_run;
1755 /* apply 2^x-1 mask */
1756 window_posn &= window_size - 1;
1757 /* runs can't straddle the window wraparound */
1758 if ((window_posn + this_run) > window_size)
1759 return DECR_DATAFORMAT;
1761 switch (LZX(block_type)) {
1763 case LZX_BLOCKTYPE_VERBATIM:
1764 while (this_run > 0) {
1765 READ_HUFFSYM(MAINTREE, main_element);
1767 if (main_element < LZX_NUM_CHARS) {
1768 /* literal: 0 to LZX_NUM_CHARS-1 */
1769 window[window_posn++] = main_element;
1773 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1774 main_element -= LZX_NUM_CHARS;
1776 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1777 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1778 READ_HUFFSYM(LENGTH, length_footer);
1779 match_length += length_footer;
1781 match_length += LZX_MIN_MATCH;
1783 match_offset = main_element >> 3;
1785 if (match_offset > 2) {
1786 /* not repeated offset */
1787 if (match_offset != 3) {
1788 extra = CAB(extra_bits)[match_offset];
1789 READ_BITS(verbatim_bits, extra);
1790 match_offset = CAB(lzx_position_base)[match_offset]
1791 - 2 + verbatim_bits;
1797 /* update repeated offset LRU queue */
1798 R2 = R1; R1 = R0; R0 = match_offset;
1800 else if (match_offset == 0) {
1803 else if (match_offset == 1) {
1805 R1 = R0; R0 = match_offset;
1807 else /* match_offset == 2 */ {
1809 R2 = R0; R0 = match_offset;
1812 rundest = window + window_posn;
1813 this_run -= match_length;
1815 /* copy any wrapped around source data */
1816 if (window_posn >= match_offset) {
1818 runsrc = rundest - match_offset;
1820 runsrc = rundest + (window_size - match_offset);
1821 copy_length = match_offset - window_posn;
1822 if (copy_length < match_length) {
1823 match_length -= copy_length;
1824 window_posn += copy_length;
1825 while (copy_length-- > 0) *rundest++ = *runsrc++;
1829 window_posn += match_length;
1831 /* copy match data - no worries about destination wraps */
1832 while (match_length-- > 0) *rundest++ = *runsrc++;
1837 case LZX_BLOCKTYPE_ALIGNED:
1838 while (this_run > 0) {
1839 READ_HUFFSYM(MAINTREE, main_element);
1841 if (main_element < LZX_NUM_CHARS) {
1842 /* literal: 0 to LZX_NUM_CHARS-1 */
1843 window[window_posn++] = main_element;
1847 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1848 main_element -= LZX_NUM_CHARS;
1850 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1851 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1852 READ_HUFFSYM(LENGTH, length_footer);
1853 match_length += length_footer;
1855 match_length += LZX_MIN_MATCH;
1857 match_offset = main_element >> 3;
1859 if (match_offset > 2) {
1860 /* not repeated offset */
1861 extra = CAB(extra_bits)[match_offset];
1862 match_offset = CAB(lzx_position_base)[match_offset] - 2;
1864 /* verbatim and aligned bits */
1866 READ_BITS(verbatim_bits, extra);
1867 match_offset += (verbatim_bits << 3);
1868 READ_HUFFSYM(ALIGNED, aligned_bits);
1869 match_offset += aligned_bits;
1871 else if (extra == 3) {
1872 /* aligned bits only */
1873 READ_HUFFSYM(ALIGNED, aligned_bits);
1874 match_offset += aligned_bits;
1876 else if (extra > 0) { /* extra==1, extra==2 */
1877 /* verbatim bits only */
1878 READ_BITS(verbatim_bits, extra);
1879 match_offset += verbatim_bits;
1881 else /* extra == 0 */ {
1886 /* update repeated offset LRU queue */
1887 R2 = R1; R1 = R0; R0 = match_offset;
1889 else if (match_offset == 0) {
1892 else if (match_offset == 1) {
1894 R1 = R0; R0 = match_offset;
1896 else /* match_offset == 2 */ {
1898 R2 = R0; R0 = match_offset;
1901 rundest = window + window_posn;
1902 this_run -= match_length;
1904 /* copy any wrapped around source data */
1905 if (window_posn >= match_offset) {
1907 runsrc = rundest - match_offset;
1909 runsrc = rundest + (window_size - match_offset);
1910 copy_length = match_offset - window_posn;
1911 if (copy_length < match_length) {
1912 match_length -= copy_length;
1913 window_posn += copy_length;
1914 while (copy_length-- > 0) *rundest++ = *runsrc++;
1918 window_posn += match_length;
1920 /* copy match data - no worries about destination wraps */
1921 while (match_length-- > 0) *rundest++ = *runsrc++;
1926 case LZX_BLOCKTYPE_UNCOMPRESSED:
1927 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1928 memcpy(window + window_posn, inpos, (size_t) this_run);
1929 inpos += this_run; window_posn += this_run;
1933 return DECR_ILLEGALDATA; /* might as well */
1939 if (togo != 0) return DECR_ILLEGALDATA;
1940 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1941 outlen, (size_t) outlen);
1943 LZX(window_posn) = window_posn;
1948 /* intel E8 decoding */
1949 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1950 if (outlen <= 6 || !LZX(intel_started)) {
1951 LZX(intel_curpos) += outlen;
1954 cab_UBYTE *data = CAB(outbuf);
1955 cab_UBYTE *dataend = data + outlen - 10;
1956 cab_LONG curpos = LZX(intel_curpos);
1957 cab_LONG filesize = LZX(intel_filesize);
1958 cab_LONG abs_off, rel_off;
1960 LZX(intel_curpos) = curpos + outlen;
1962 while (data < dataend) {
1963 if (*data++ != 0xE8) { curpos++; continue; }
1964 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1965 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1966 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1967 data[0] = (cab_UBYTE) rel_off;
1968 data[1] = (cab_UBYTE) (rel_off >> 8);
1969 data[2] = (cab_UBYTE) (rel_off >> 16);
1970 data[3] = (cab_UBYTE) (rel_off >> 24);
1980 /**********************************************************
1981 * fdi_decomp (internal)
1983 * Decompress the requested number of bytes. If savemode is zero,
1984 * do not save the output anywhere, just plow through blocks until we
1985 * reach the specified (uncompressed) distance from the starting point,
1986 * and remember the position of the cabfile pointer (and which cabfile)
1987 * after we are done; otherwise, save the data out to CAB(filehf),
1988 * decompressing the requested number of bytes and writing them out. This
1989 * is also where we jump to additional cabinets in the case of split
1990 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1992 static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
1993 char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
1995 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
1996 cab_UBYTE buf[cfdata_SIZEOF], *data;
1997 cab_UWORD inlen, len, outlen, cando;
2000 fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
2002 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
2005 /* cando = the max number of bytes we can do */
2006 cando = CAB(outlen);
2007 if (cando > bytes) cando = bytes;
2010 if (cando && savemode)
2011 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
2013 CAB(outpos) += cando;
2014 CAB(outlen) -= cando;
2015 bytes -= cando; if (!bytes) break;
2017 /* we only get here if we emptied the output buffer */
2019 /* read data header + data */
2021 while (outlen == 0) {
2022 /* read the block header, skip the reserved part */
2023 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
2026 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
2029 /* we shouldn't get blocks over CAB_INPUTMAX in size */
2030 data = CAB(inbuf) + inlen;
2031 len = EndGetI16(buf+cfdata_CompressedSize);
2033 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
2034 if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
2037 /* clear two bytes after read-in data */
2038 data[len+1] = data[len+2] = 0;
2040 /* perform checksum test on the block (if one is stored) */
2041 cksum = EndGetI32(buf+cfdata_CheckSum);
2042 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
2043 return DECR_CHECKSUM; /* checksum is wrong */
2045 outlen = EndGetI16(buf+cfdata_UncompressedSize);
2047 /* outlen=0 means this block was the last contiguous part
2048 of a split block, continued in the next cabinet */
2050 int pathlen, filenamelen, idx, i, cabhf;
2051 char fullpath[MAX_PATH], userpath[256];
2052 FDINOTIFICATION fdin;
2053 FDICABINETINFO fdici;
2054 char emptystring = '\0';
2056 int success = FALSE;
2057 struct fdi_folder *fol = NULL, *linkfol = NULL;
2058 struct fdi_file *file = NULL, *linkfile = NULL;
2062 /* set up the next decomp_state... */
2064 if (!cab->mii.hasnext) return DECR_INPUT;
2066 if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
2067 return DECR_NOMEMORY;
2069 ZeroMemory(cab->next, sizeof(fdi_decomp_state));
2071 /* copy pszCabPath to userpath */
2072 ZeroMemory(userpath, 256);
2073 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2075 if (pathlen < 256) {
2076 for (i = 0; i <= pathlen; i++)
2077 userpath[i] = pszCabPath[i];
2078 } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2081 /* initial fdintNEXT_CABINET notification */
2082 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2083 fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
2084 fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
2085 fdin.psz3 = &userpath[0];
2086 fdin.fdie = FDIERROR_NONE;
2089 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2093 pathlen = strlen(userpath);
2094 filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
2096 /* slight overestimation here to save CPU cycles in the developer's brain */
2097 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2098 ERR("MAX_PATH exceeded.\n");
2099 return DECR_ILLEGALDATA;
2102 /* paste the path and filename together */
2105 for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
2106 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2108 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
2109 fullpath[idx] = '\0';
2111 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2113 /* try to get a handle to the cabfile */
2114 cabhf = PFDI_OPEN(CAB(hfdi), fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2116 /* no file. allow the user to try again */
2117 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2118 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2123 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2124 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2125 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2129 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2130 if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
2131 WARN("FDIIsCabinet failed.\n");
2132 PFDI_CLOSE(CAB(hfdi), cabhf);
2133 fdin.fdie = FDIERROR_NOT_A_CABINET;
2134 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2138 if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
2139 WARN("Wrong Cabinet.\n");
2140 PFDI_CLOSE(CAB(hfdi), cabhf);
2141 fdin.fdie = FDIERROR_WRONG_CABINET;
2142 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2150 /* cabinet notification */
2151 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2152 fdin.setID = fdici.setID;
2153 fdin.iCabinet = fdici.iCabinet;
2155 fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2156 fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2157 fdin.psz3 = pszCabPath;
2159 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2161 cab->next->setID = fdici.setID;
2162 cab->next->iCabinet = fdici.iCabinet;
2163 cab->next->hfdi = CAB(hfdi);
2164 cab->next->filehf = CAB(filehf);
2165 cab->next->cabhf = cabhf;
2166 cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2168 cab = cab->next; /* advance to the next cabinet */
2171 for (i = 0; i < fdici.cFolders; i++) {
2172 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF)
2175 if (cab->mii.folder_resv > 0)
2176 PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2178 fol = (struct fdi_folder *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2180 ERR("out of memory!\n");
2181 return DECR_NOMEMORY;
2183 ZeroMemory(fol, sizeof(struct fdi_folder));
2184 if (!(cab->firstfol)) cab->firstfol = fol;
2186 fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2187 fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2188 fol->comp_type = EndGetI16(buf2+cffold_CompType);
2191 linkfol->next = fol;
2196 for (i = 0; i < fdici.cFiles; i++) {
2197 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2200 file = (struct fdi_file *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2202 ERR("out of memory!\n");
2203 return DECR_NOMEMORY;
2205 ZeroMemory(file, sizeof(struct fdi_file));
2206 if (!(cab->firstfile)) cab->firstfile = file;
2208 file->length = EndGetI32(buf2+cffile_UncompressedSize);
2209 file->offset = EndGetI32(buf2+cffile_FolderOffset);
2210 file->index = EndGetI16(buf2+cffile_FolderIndex);
2211 file->time = EndGetI16(buf2+cffile_Time);
2212 file->date = EndGetI16(buf2+cffile_Date);
2213 file->attribs = EndGetI16(buf2+cffile_Attribs);
2214 file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2216 if (!file->filename) return DECR_INPUT;
2219 linkfile->next = file;
2224 cab = cab->next; /* advance to the next cabinet */
2226 /* iterate files -- if we encounter the continued file, process it --
2227 otherwise, jump to the label above and keep looking */
2229 for (file = cab->firstfile; (file); file = file->next) {
2230 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2231 /* check to ensure a real match */
2232 if (strcasecmp(fi->filename, file->filename) == 0) {
2234 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2240 if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2241 "Wrong Cabinet" notification? */
2245 /* decompress block */
2246 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2248 CAB(outlen) = outlen;
2249 CAB(outpos) = CAB(outbuf);
2252 CAB(decomp_cab) = cab;
2256 /***********************************************************************
2257 * FDICopy (CABINET.22)
2259 * Iterates through the files in the Cabinet file indicated by name and
2260 * file-location. May chain forward to additional cabinets (typically
2261 * only one) if files which begin in this Cabinet are continued in another
2262 * cabinet. For each file which is partially contained in this cabinet,
2263 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2264 * notification to the pfnfdin callback. For each file which begins in
2265 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2266 * callback, and the file is optionally decompressed and saved to disk.
2267 * Notification is not provided for files which are not at least partially
2268 * contained in the specified cabinet file.
2270 * See below for a thorough explanation of the various notification
2274 * hfdi [I] An HFDI from FDICreate
2275 * pszCabinet [I] C-style string containing the filename of the cabinet
2276 * pszCabPath [I] C-style string containing the file path of the cabinet
2277 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2278 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2279 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2281 * pvUser [I] arbitrary void * value which is passed to callbacks.
2284 * TRUE if successful.
2285 * FALSE if unsuccessful (error information is provided in the ERF structure
2286 * associated with the provided decompression handle by FDICreate).
2290 * Two pointers to callback functions are provided as parameters to FDICopy:
2291 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2292 * types are as follows:
2294 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2295 * PFDINOTIFICATION pfdin );
2297 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2299 * You can create functions of this type using the FNFDINOTIFY() and
2300 * FNFDIDECRYPT() macros, respectively. For example:
2302 * FNFDINOTIFY(mycallback) {
2303 * / * use variables fdint and pfdin to process notification * /
2306 * The second callback, which could be used for decrypting encrypted data,
2307 * is not used at all.
2309 * Each notification informs the user of some event which has occurred during
2310 * decompression of the cabinet file; each notification is also an opportunity
2311 * for the callee to abort decompression. The information provided to the
2312 * callback and the meaning of the callback's return value vary drastically
2313 * across the various types of notification. The type of notification is the
2314 * fdint parameter; all other information is provided to the callback in
2315 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2316 * pfdin. The only part of that structure which is assigned for every callback
2317 * is the pv element, which contains the arbitrary value which was passed to
2318 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2319 * is highly dependent on fdint).
2321 * If you encounter unknown notifications, you should return zero if you want
2322 * decompression to continue (or -1 to abort). All strings used in the
2323 * callbacks are regular C-style strings. Detailed descriptions of each
2324 * notification type follow:
2326 * fdintCABINET_INFO:
2328 * This is the first notification provided after calling FDICopy, and provides
2329 * the user with various information about the cabinet. Note that this is
2330 * called for each cabinet FDICopy opens, not just the first one. In the
2331 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2332 * next cabinet file in the set after the one just loaded (if any), psz2
2333 * contains a pointer to the name or "info" of the next disk, psz3
2334 * contains a pointer to the file-path of the current cabinet, setID
2335 * contains an arbitrary constant associated with this set of cabinet files,
2336 * and iCabinet contains the numerical index of the current cabinet within
2337 * that set. Return zero, or -1 to abort.
2339 * fdintPARTIAL_FILE:
2341 * This notification is provided when FDICopy encounters a part of a file
2342 * contained in this cabinet which is missing its beginning. Files can be
2343 * split across cabinets, so this is not necessarily an abnormality; it just
2344 * means that the file in question begins in another cabinet. No file
2345 * corresponding to this notification is extracted from the cabinet. In the
2346 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2347 * partial file, psz2 contains a pointer to the file name of the cabinet in
2348 * which this file begins, and psz3 contains a pointer to the disk name or
2349 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2353 * This notification is provided when FDICopy encounters a file which starts
2354 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2355 * look for files in cabinets after the first one). One notification will be
2356 * sent for each such file, before the file is decompressed. By returning
2357 * zero, the callback can instruct FDICopy to skip the file. In the structure
2358 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2359 * the size of the file (uncompressed), attribs contains the file attributes,
2360 * and date and time contain the date and time of the file. attributes, date,
2361 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2362 * for the entire cabinet, 0 to skip just this file but continue scanning the
2363 * cabinet for more files, or an FDIClose()-compatible file-handle.
2365 * fdintCLOSE_FILE_INFO:
2367 * This notification is important, don't forget to implement it. This
2368 * notification indicates that a file has been successfully uncompressed and
2369 * written to disk. Upon receipt of this notification, the callee is expected
2370 * to close the file handle, to set the attributes and date/time of the
2371 * closed file, and possibly to execute the file. In the structure pointed to
2372 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2373 * open file handle (close it), cb contains 1 or zero, indicating respectively
2374 * that the callee should or should not execute the file, and date, time
2375 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2376 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2377 * do so. Return TRUE, or FALSE to abort decompression.
2379 * fdintNEXT_CABINET:
2381 * This notification is called when FDICopy must load in another cabinet. This
2382 * can occur when a file's data is "split" across multiple cabinets. The
2383 * callee has the opportunity to request that FDICopy look in a different file
2384 * path for the specified cabinet file, by writing that data into a provided
2385 * buffer (see below for more information). This notification will be received
2386 * more than once per-cabinet in the instance that FDICopy failed to find a
2387 * valid cabinet at the location specified by the first per-cabinet
2388 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2389 * structure pointed to by pfdin indicates the error which prevented FDICopy
2390 * from proceeding successfully. Return zero to indicate success, or -1 to
2391 * indicate failure and abort FDICopy.
2393 * Upon receipt of this notification, the structure pointed to by pfdin will
2394 * contain the following values: psz1 pointing to the name of the cabinet
2395 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2396 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2397 * and fdie containing either FDIERROR_NONE, or one of the following:
2399 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2400 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2401 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2402 * FDIERROR_WRONG_CABINET.
2404 * The callee may choose to change the path where FDICopy will look for the
2405 * cabinet after this notification. To do so, the caller may write the new
2406 * pathname to the buffer pointed to by psz3, which is 256 characters in
2407 * length, including the terminating null character, before returning zero.
2411 * Undocumented and unimplemented in wine, this seems to be sent each time
2412 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2413 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2414 * provides information about the current cabinet instead of the next one....
2415 * this is just a guess, it has not been looked at closely.
2420 BOOL __cdecl FDICopy(
2425 PFNFDINOTIFY pfnfdin,
2426 PFNFDIDECRYPT pfnfdid,
2429 FDICABINETINFO fdici;
2430 FDINOTIFICATION fdin;
2431 int cabhf, filehf = 0, idx;
2433 char fullpath[MAX_PATH];
2434 size_t pathlen, filenamelen;
2435 char emptystring = '\0';
2437 struct fdi_folder *fol = NULL, *linkfol = NULL;
2438 struct fdi_file *file = NULL, *linkfile = NULL;
2439 fdi_decomp_state _decomp_state;
2440 fdi_decomp_state *decomp_state = &_decomp_state;
2442 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, "
2443 "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2444 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2446 if (!REALLY_IS_FDI(hfdi)) {
2447 SetLastError(ERROR_INVALID_HANDLE);
2451 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2453 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2454 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2456 /* slight overestimation here to save CPU cycles in the developer's brain */
2457 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2458 ERR("MAX_PATH exceeded.\n");
2459 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2460 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2461 PFDI_INT(hfdi)->perf->fError = TRUE;
2462 SetLastError(ERROR_FILE_NOT_FOUND);
2466 /* paste the path and filename together */
2469 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2470 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2472 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2473 fullpath[idx] = '\0';
2475 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2477 /* get a handle to the cabfile */
2478 cabhf = PFDI_OPEN(hfdi, fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2480 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2481 PFDI_INT(hfdi)->perf->fError = TRUE;
2482 SetLastError(ERROR_FILE_NOT_FOUND);
2487 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2488 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2489 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2490 PFDI_INT(hfdi)->perf->fError = TRUE;
2491 SetLastError(ERROR_FILE_NOT_FOUND);
2495 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2496 if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2497 ERR("FDIIsCabinet failed.\n");
2498 PFDI_CLOSE(hfdi, cabhf);
2502 /* cabinet notification */
2503 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2504 fdin.setID = fdici.setID;
2505 fdin.iCabinet = fdici.iCabinet;
2507 fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2508 fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2509 fdin.psz3 = pszCabPath;
2511 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2512 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2513 PFDI_INT(hfdi)->perf->erfType = 0;
2514 PFDI_INT(hfdi)->perf->fError = TRUE;
2518 CAB(setID) = fdici.setID;
2519 CAB(iCabinet) = fdici.iCabinet;
2523 for (i = 0; i < fdici.cFolders; i++) {
2524 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2525 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2526 PFDI_INT(hfdi)->perf->erfType = 0;
2527 PFDI_INT(hfdi)->perf->fError = TRUE;
2531 if (CAB(mii).folder_resv > 0)
2532 PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2534 fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2536 ERR("out of memory!\n");
2537 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2538 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2539 PFDI_INT(hfdi)->perf->fError = TRUE;
2540 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2543 ZeroMemory(fol, sizeof(struct fdi_folder));
2544 if (!CAB(firstfol)) CAB(firstfol) = fol;
2546 fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2547 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2548 fol->comp_type = EndGetI16(buf+cffold_CompType);
2551 linkfol->next = fol;
2556 for (i = 0; i < fdici.cFiles; i++) {
2557 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2558 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2559 PFDI_INT(hfdi)->perf->erfType = 0;
2560 PFDI_INT(hfdi)->perf->fError = TRUE;
2564 file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2566 ERR("out of memory!\n");
2567 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2568 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2569 PFDI_INT(hfdi)->perf->fError = TRUE;
2570 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2573 ZeroMemory(file, sizeof(struct fdi_file));
2574 if (!CAB(firstfile)) CAB(firstfile) = file;
2576 file->length = EndGetI32(buf+cffile_UncompressedSize);
2577 file->offset = EndGetI32(buf+cffile_FolderOffset);
2578 file->index = EndGetI16(buf+cffile_FolderIndex);
2579 file->time = EndGetI16(buf+cffile_Time);
2580 file->date = EndGetI16(buf+cffile_Date);
2581 file->attribs = EndGetI16(buf+cffile_Attribs);
2582 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2584 if (!file->filename) {
2585 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2586 PFDI_INT(hfdi)->perf->erfType = 0;
2587 PFDI_INT(hfdi)->perf->fError = TRUE;
2592 linkfile->next = file;
2596 for (file = CAB(firstfile); (file); file = file->next) {
2599 * FIXME: This implementation keeps multiple cabinet files open at once
2600 * when encountering a split cabinet. It is a quirk of this implementation
2601 * that sometimes we decrypt the same block of data more than once, to find
2602 * the right starting point for a file, moving the file-pointer backwards.
2603 * If we kept a cache of certain file-pointer information, we could eliminate
2604 * that behavior... in fact I am not sure that the caching we already have
2605 * is not sufficient.
2607 * The current implementation seems to work fine in straightforward situations
2608 * where all the cabinet files needed for decryption are simultaneously
2609 * available. But presumably, the API is supposed to support cabinets which
2610 * are split across multiple CDROMS; we may need to change our implementation
2611 * to strictly serialize it's file usage so that it opens only one cabinet
2612 * at a time. Some experimentation with Windows is needed to figure out the
2613 * precise semantics required. The relevant code is here and in fdi_decomp().
2616 /* partial-file notification */
2617 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2619 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2620 * and perform some tests to figure out the right behavior. The SDK says
2621 * FDICopy will notify the user of the filename and "disk name" (info) of
2622 * the cabinet where the spanning file /started/.
2624 * That would certainly be convenient for the API-user, who could abort,
2625 * everything (or parallelize, if that's allowed (it is in wine)), and call
2626 * FDICopy again with the provided filename, so as to avoid partial file
2627 * notification and successfully unpack. This task could be quite unpleasant
2628 * from wine's perspective: the information specifying the "start cabinet" for
2629 * a file is associated nowhere with the file header and is not to be found in
2630 * the cabinet header. We have only the index of the cabinet wherein the folder
2631 * begins, which contains the file. To find that cabinet, we must consider the
2632 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2633 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2636 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2637 * cabinet other than the active one might be at another filepath than the
2638 * current one, or on another CDROM. This could get rather dicey, especially
2639 * if we imagine parallelized access to the FDICopy API.
2641 * The current implementation punts -- it just returns the previous cabinet and
2642 * it's info from the header of this cabinet. This provides the right answer in
2643 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2646 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2648 fdin.psz1 = (char *)file->filename;
2649 fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2650 fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2652 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2653 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2654 PFDI_INT(hfdi)->perf->erfType = 0;
2655 PFDI_INT(hfdi)->perf->fError = TRUE;
2658 /* I don't think we are supposed to decompress partial files. This prevents it. */
2659 file->oppressed = TRUE;
2661 if (file->oppressed) {
2664 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2666 fdin.psz1 = (char *)file->filename;
2667 fdin.cb = file->length;
2668 fdin.date = file->date;
2669 fdin.time = file->time;
2670 fdin.attribs = file->attribs;
2671 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2672 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2673 PFDI_INT(hfdi)->perf->erfType = 0;
2674 PFDI_INT(hfdi)->perf->fError = TRUE;
2680 /* find the folder for this file if necc. */
2684 fol = CAB(firstfol);
2685 if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2686 /* pick the last folder */
2687 while (fol->next) fol = fol->next;
2689 for (i2 = 0; (i2 < file->index); i2++)
2690 if (fol->next) /* bug resistance, should always be true */
2696 cab_UWORD comptype = fol->comp_type;
2697 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2698 int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2701 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2703 /* set up decomp_state */
2705 CAB(filehf) = filehf;
2707 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2708 if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2710 TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2712 /* free stuff for the old decompresser */
2714 case cffoldCOMPTYPE_LZX:
2716 PFDI_FREE(hfdi, LZX(window));
2720 case cffoldCOMPTYPE_QUANTUM:
2722 PFDI_FREE(hfdi, QTM(window));
2728 CAB(decomp_cab) = NULL;
2729 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2733 /* initialize the new decompresser */
2735 case cffoldCOMPTYPE_NONE:
2736 CAB(decompress) = NONEfdi_decomp;
2738 case cffoldCOMPTYPE_MSZIP:
2739 CAB(decompress) = ZIPfdi_decomp;
2741 case cffoldCOMPTYPE_QUANTUM:
2742 CAB(decompress) = QTMfdi_decomp;
2743 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2745 case cffoldCOMPTYPE_LZX:
2746 CAB(decompress) = LZXfdi_decomp;
2747 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2750 err = DECR_DATAFORMAT;
2760 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2761 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2762 PFDI_INT(hfdi)->perf->fError = TRUE;
2763 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2766 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2767 PFDI_INT(hfdi)->perf->erfOper = 0;
2768 PFDI_INT(hfdi)->perf->fError = TRUE;
2772 if (file->offset > CAB(offset)) {
2773 /* decode bytes and send them to /dev/null */
2774 switch ((err = fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser))) {
2777 case DECR_USERABORT:
2778 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2779 PFDI_INT(hfdi)->perf->erfType = 0;
2780 PFDI_INT(hfdi)->perf->fError = TRUE;
2783 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2784 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2785 PFDI_INT(hfdi)->perf->fError = TRUE;
2786 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2789 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2790 PFDI_INT(hfdi)->perf->erfOper = 0;
2791 PFDI_INT(hfdi)->perf->fError = TRUE;
2794 CAB(offset) = file->offset;
2797 /* now do the actual decompression */
2798 err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2799 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2801 /* fdintCLOSE_FILE_INFO notification */
2802 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2804 fdin.psz1 = (char *)file->filename;
2806 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2807 fdin.date = file->date;
2808 fdin.time = file->time;
2809 fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2810 ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2816 case DECR_USERABORT:
2817 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2818 PFDI_INT(hfdi)->perf->erfType = 0;
2819 PFDI_INT(hfdi)->perf->fError = TRUE;
2822 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2823 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2824 PFDI_INT(hfdi)->perf->fError = TRUE;
2825 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2828 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2829 PFDI_INT(hfdi)->perf->erfOper = 0;
2830 PFDI_INT(hfdi)->perf->fError = TRUE;
2836 /* free decompression temps */
2837 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2838 case cffoldCOMPTYPE_LZX:
2840 PFDI_FREE(hfdi, LZX(window));
2844 case cffoldCOMPTYPE_QUANTUM:
2846 PFDI_FREE(hfdi, QTM(window));
2852 while (decomp_state) {
2853 fdi_decomp_state *prev_fds;
2855 PFDI_CLOSE(hfdi, CAB(cabhf));
2857 /* free the storage remembered by mii */
2858 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2859 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2860 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2861 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2863 while (CAB(firstfol)) {
2864 fol = CAB(firstfol);
2865 CAB(firstfol) = CAB(firstfol)->next;
2866 PFDI_FREE(hfdi, fol);
2868 while (CAB(firstfile)) {
2869 file = CAB(firstfile);
2870 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2871 CAB(firstfile) = CAB(firstfile)->next;
2872 PFDI_FREE(hfdi, file);
2874 prev_fds = decomp_state;
2875 decomp_state = CAB(next);
2876 if (prev_fds != &_decomp_state)
2877 PFDI_FREE(hfdi, prev_fds);
2882 bail_and_fail: /* here we free ram before error returns */
2884 /* free decompression temps */
2885 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2886 case cffoldCOMPTYPE_LZX:
2888 PFDI_FREE(hfdi, LZX(window));
2892 case cffoldCOMPTYPE_QUANTUM:
2894 PFDI_FREE(hfdi, QTM(window));
2900 if (filehf) PFDI_CLOSE(hfdi, filehf);
2902 while (decomp_state) {
2903 fdi_decomp_state *prev_fds;
2905 PFDI_CLOSE(hfdi, CAB(cabhf));
2907 /* free the storage remembered by mii */
2908 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2909 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2910 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2911 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2913 while (CAB(firstfol)) {
2914 fol = CAB(firstfol);
2915 CAB(firstfol) = CAB(firstfol)->next;
2916 PFDI_FREE(hfdi, fol);
2918 while (CAB(firstfile)) {
2919 file = CAB(firstfile);
2920 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2921 CAB(firstfile) = CAB(firstfile)->next;
2922 PFDI_FREE(hfdi, file);
2924 prev_fds = decomp_state;
2925 decomp_state = CAB(next);
2926 if (prev_fds != &_decomp_state)
2927 PFDI_FREE(hfdi, prev_fds);
2933 /***********************************************************************
2934 * FDIDestroy (CABINET.23)
2936 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2937 * of FDICopy. Only reason for failure would be an invalid handle.
2940 * hfdi [I] The HFDI to free
2946 BOOL __cdecl FDIDestroy(HFDI hfdi)
2948 TRACE("(hfdi == ^%p)\n", hfdi);
2949 if (REALLY_IS_FDI(hfdi)) {
2950 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2951 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2954 SetLastError(ERROR_INVALID_HANDLE);
2959 /***********************************************************************
2960 * FDITruncateCabinet (CABINET.24)
2962 * Removes all folders of a cabinet file after and including the
2963 * specified folder number.
2966 * hfdi [I] Handle to the FDI context.
2967 * pszCabinetName [I] Filename of the cabinet.
2968 * iFolderToDelete [I] Index of the first folder to delete.
2975 * The PFNWRITE function supplied to FDICreate must truncate the
2976 * file at the current position if the number of bytes to write is 0.
2978 BOOL __cdecl FDITruncateCabinet(
2980 char *pszCabinetName,
2981 USHORT iFolderToDelete)
2983 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2984 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2986 if (!REALLY_IS_FDI(hfdi)) {
2987 SetLastError(ERROR_INVALID_HANDLE);
2991 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);