shell32: Added some test to document native ITEMIDLIST format.
[wine/wine64.git] / dlls / cabinet / fdi.c
blob149171263c4c9b58c65e9bedb7cd9075cedd0844
1 /*
2 * File Decompression Interface
4 * Copyright 2000-2002 Stuart Caie
5 * Copyright 2002 Patrik Stridvall
6 * Copyright 2003 Greg Turner
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * This is a largely redundant reimplementation of the stuff in cabextract.c. It
24 * would be theoretically preferable to have only one, shared implementation, however
25 * there are semantic differences which may discourage efforts to unify the two. It
26 * should be possible, if awkward, to go back and reimplement cabextract.c using FDI.
27 * But this approach would be quite a bit less performant. Probably a better way
28 * would be to create a "library" of routines in cabextract.c which do the actual
29 * decompression, and have both fdi.c and cabextract share those routines. The rest
30 * of the code is not sufficiently similar to merit a shared implementation.
32 * The worst thing about this API is the bug. "The bug" is this: when you extract a
33 * cabinet, it /always/ informs you (via the hasnext field of PFDICABINETINFO), that
34 * there is no subsequent cabinet, even if there is one. wine faithfully reproduces
35 * this behavior.
37 * TODO:
39 * Wine does not implement the AFAIK undocumented "enumerate" callback during
40 * FDICopy. It is implemented in Windows and therefore worth investigating...
42 * Lots of pointers flying around here... am I leaking RAM?
44 * WTF is FDITruncate?
46 * Probably, I need to weed out some dead code-paths.
48 * Test unit(s).
50 * The fdintNEXT_CABINET callbacks are probably not working quite as they should.
51 * There are several FIXME's in the source describing some of the deficiencies in
52 * some detail. Additionally, we do not do a very good job of returning the right
53 * error codes to this callback.
55 * FDICopy and fdi_decomp are incomprehensibly large; separating these into smaller
56 * functions would be nice.
58 * -gmt
61 #include "config.h"
63 #include <stdarg.h>
64 #include <stdio.h>
66 #include "windef.h"
67 #include "winbase.h"
68 #include "winerror.h"
69 #include "fdi.h"
70 #include "cabinet.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
76 THOSE_ZIP_CONSTS;
78 struct fdi_file {
79 struct fdi_file *next; /* next file in sequence */
80 LPCSTR filename; /* output name of file */
81 int fh; /* open file handle or NULL */
82 cab_ULONG length; /* uncompressed length of file */
83 cab_ULONG offset; /* uncompressed offset in folder */
84 cab_UWORD index; /* magic index number of folder */
85 cab_UWORD time, date, attribs; /* MS-DOS time/date/attributes */
86 BOOL oppressed; /* never to be processed */
89 struct fdi_folder {
90 struct fdi_folder *next;
91 cab_off_t offset; /* offset to data blocks (32 bit) */
92 cab_UWORD comp_type; /* compression format/window size */
93 cab_ULONG comp_size; /* compressed size of folder */
94 cab_UBYTE num_splits; /* number of split blocks + 1 */
95 cab_UWORD num_blocks; /* total number of blocks */
99 * this structure fills the gaps between what is available in a PFDICABINETINFO
100 * vs what is needed by FDICopy. Memory allocated for these becomes the responsibility
101 * of the caller to free. Yes, I am aware that this is totally, utterly inelegant.
102 * To make things even more unnecessarily confusing, we now attach these to the
103 * fdi_decomp_state.
105 typedef struct {
106 char *prevname, *previnfo;
107 char *nextname, *nextinfo;
108 BOOL hasnext; /* bug free indicator */
109 int folder_resv, header_resv;
110 cab_UBYTE block_resv;
111 } MORE_ISCAB_INFO, *PMORE_ISCAB_INFO;
114 * ugh, well, this ended up being pretty damn silly...
115 * now that I've conceded to build equivalent structures to struct cab.*,
116 * I should have just used those, or, better yet, unified the two... sue me.
117 * (Note to Microsoft: That's a joke. Please /don't/ actually sue me! -gmt).
118 * Nevertheless, I've come this far, it works, so I'm not gonna change it
119 * for now. This implementation has significant semantic differences anyhow.
122 typedef struct fdi_cds_fwd {
123 void *hfdi; /* the hfdi we are using */
124 int filehf, cabhf; /* file handle we are using */
125 struct fdi_folder *current; /* current folder we're extracting from */
126 cab_ULONG offset; /* uncompressed offset within folder */
127 cab_UBYTE *outpos; /* (high level) start of data to use up */
128 cab_UWORD outlen; /* (high level) amount of data to use up */
129 int (*decompress)(int, int, struct fdi_cds_fwd *); /* chosen compress fn */
130 cab_UBYTE inbuf[CAB_INPUTMAX+2]; /* +2 for lzx bitbuffer overflows! */
131 cab_UBYTE outbuf[CAB_BLOCKMAX];
132 union {
133 struct ZIPstate zip;
134 struct QTMstate qtm;
135 struct LZXstate lzx;
136 } methods;
137 /* some temp variables for use during decompression */
138 cab_UBYTE q_length_base[27], q_length_extra[27], q_extra_bits[42];
139 cab_ULONG q_position_base[42];
140 cab_ULONG lzx_position_base[51];
141 cab_UBYTE extra_bits[51];
142 USHORT setID; /* Cabinet set ID */
143 USHORT iCabinet; /* Cabinet number in set (0 based) */
144 struct fdi_cds_fwd *decomp_cab;
145 MORE_ISCAB_INFO mii;
146 struct fdi_folder *firstfol;
147 struct fdi_file *firstfile;
148 struct fdi_cds_fwd *next;
149 } fdi_decomp_state;
151 /***********************************************************************
152 * FDICreate (CABINET.20)
154 * Provided with several callbacks (all of them are mandatory),
155 * returns a handle which can be used to perform operations
156 * on cabinet files.
158 * PARAMS
159 * pfnalloc [I] A pointer to a function which allocates ram. Uses
160 * the same interface as malloc.
161 * pfnfree [I] A pointer to a function which frees ram. Uses the
162 * same interface as free.
163 * pfnopen [I] A pointer to a function which opens a file. Uses
164 * the same interface as _open.
165 * pfnread [I] A pointer to a function which reads from a file into
166 * a caller-provided buffer. Uses the same interface
167 * as _read
168 * pfnwrite [I] A pointer to a function which writes to a file from
169 * a caller-provided buffer. Uses the same interface
170 * as _write.
171 * pfnclose [I] A pointer to a function which closes a file handle.
172 * Uses the same interface as _close.
173 * pfnseek [I] A pointer to a function which seeks in a file.
174 * Uses the same interface as _lseek.
175 * cpuType [I] The type of CPU; ignored in wine (recommended value:
176 * cpuUNKNOWN, aka -1).
177 * perf [IO] A pointer to an ERF structure. When FDICreate
178 * returns an error condition, error information may
179 * be found here as well as from GetLastError.
181 * RETURNS
182 * On success, returns an FDI handle of type HFDI.
183 * On failure, the NULL file handle is returned. Error
184 * info can be retrieved from perf.
186 * INCLUDES
187 * fdi.h
190 HFDI __cdecl FDICreate(
191 PFNALLOC pfnalloc,
192 PFNFREE pfnfree,
193 PFNOPEN pfnopen,
194 PFNREAD pfnread,
195 PFNWRITE pfnwrite,
196 PFNCLOSE pfnclose,
197 PFNSEEK pfnseek,
198 int cpuType,
199 PERF perf)
201 HFDI rv;
203 TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, \
204 pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
205 pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
206 cpuType, perf);
208 if ((!pfnalloc) || (!pfnfree)) {
209 perf->erfOper = FDIERROR_NONE;
210 perf->erfType = ERROR_BAD_ARGUMENTS;
211 perf->fError = TRUE;
213 SetLastError(ERROR_BAD_ARGUMENTS);
214 return NULL;
217 if (!((rv = ((HFDI) (*pfnalloc)(sizeof(FDI_Int)))))) {
218 perf->erfOper = FDIERROR_ALLOC_FAIL;
219 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
220 perf->fError = TRUE;
222 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
223 return NULL;
226 PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
227 PFDI_INT(rv)->pfnalloc = pfnalloc;
228 PFDI_INT(rv)->pfnfree = pfnfree;
229 PFDI_INT(rv)->pfnopen = pfnopen;
230 PFDI_INT(rv)->pfnread = pfnread;
231 PFDI_INT(rv)->pfnwrite = pfnwrite;
232 PFDI_INT(rv)->pfnclose = pfnclose;
233 PFDI_INT(rv)->pfnseek = pfnseek;
234 /* no-brainer: we ignore the cpu type; this is only used
235 for the 16-bit versions in Windows anyhow... */
236 PFDI_INT(rv)->perf = perf;
238 return rv;
241 /*******************************************************************
242 * FDI_getoffset (internal)
244 * returns the file pointer position of a file handle.
246 static long FDI_getoffset(HFDI hfdi, INT_PTR hf)
248 return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
251 /**********************************************************************
252 * FDI_realloc (internal)
254 * we can't use _msize; the user might not be using malloc, so we require
255 * an explicit specification of the previous size. inefficient.
257 static void *FDI_realloc(HFDI hfdi, void *mem, size_t prevsize, size_t newsize)
259 void *rslt = NULL;
260 char *irslt, *imem;
261 size_t copysize = (prevsize < newsize) ? prevsize : newsize;
262 if (prevsize == newsize) return mem;
263 rslt = PFDI_ALLOC(hfdi, newsize);
264 if (rslt)
265 for (irslt = (char *)rslt, imem = (char *)mem; (copysize); copysize--)
266 *irslt++ = *imem++;
267 PFDI_FREE(hfdi, mem);
268 return rslt;
271 /**********************************************************************
272 * FDI_read_string (internal)
274 * allocate and read an arbitrarily long string from the cabinet
276 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
278 size_t len=256,
279 oldlen = 0,
280 base = FDI_getoffset(hfdi, hf),
281 maxlen = cabsize - base;
282 BOOL ok = FALSE;
283 unsigned int i;
284 cab_UBYTE *buf = NULL;
286 TRACE("(hfdi == ^%p, hf == %d)\n", hfdi, hf);
288 do {
289 if (len > maxlen) len = maxlen;
290 if (!(buf = FDI_realloc(hfdi, buf, oldlen, len))) break;
291 oldlen = len;
292 if (!PFDI_READ(hfdi, hf, buf, len)) break;
294 /* search for a null terminator in what we've just read */
295 for (i=0; i < len; i++) {
296 if (!buf[i]) {ok=TRUE; break;}
299 if (!ok) {
300 if (len == maxlen) {
301 ERR("cabinet is truncated\n");
302 break;
304 len += 256;
305 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
307 } while (!ok);
309 if (!ok) {
310 if (buf)
311 PFDI_FREE(hfdi, buf);
312 else
313 ERR("out of memory!\n");
314 return NULL;
317 /* otherwise, set the stream to just after the string and return */
318 PFDI_SEEK(hfdi, hf, base + ((cab_off_t) strlen((char *) buf)) + 1, SEEK_SET);
320 return (char *) buf;
323 /******************************************************************
324 * FDI_read_entries (internal)
326 * process the cabinet header in the style of FDIIsCabinet, but
327 * without the sanity checks (and bug)
329 static BOOL FDI_read_entries(
330 HFDI hfdi,
331 INT_PTR hf,
332 PFDICABINETINFO pfdici,
333 PMORE_ISCAB_INFO pmii)
335 int num_folders, num_files, header_resv, folder_resv = 0;
336 LONG base_offset, cabsize;
337 USHORT setid, cabidx, flags;
338 cab_UBYTE buf[64], block_resv;
339 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
341 TRACE("(hfdi == ^%p, hf == %d, pfdici == ^%p)\n", hfdi, hf, pfdici);
344 * FIXME: I just noticed that I am memorizing the initial file pointer
345 * offset and restoring it before reading in the rest of the header
346 * information in the cabinet. Perhaps that's correct -- that is, perhaps
347 * this API is supposed to support "streaming" cabinets which are embedded
348 * in other files, or cabinets which begin at file offsets other than zero.
349 * Otherwise, I should instead go to the absolute beginning of the file.
350 * (Either way, the semantics of wine's FDICopy require me to leave the
351 * file pointer where it is afterwards -- If Windows does not do so, we
352 * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
354 * So, the answer lies in Windows; will native cabinet.dll recognize a
355 * cabinet "file" embedded in another file? Note that cabextract.c does
356 * support this, which implies that Microsoft's might. I haven't tried it
357 * yet so I don't know. ATM, most of wine's FDI cabinet routines (except
358 * this one) would not work in this way. To fix it, we could just make the
359 * various references to absolute file positions in the code relative to an
360 * initial "beginning" offset. Because the FDICopy API doesn't take a
361 * file-handle like this one, we would therein need to search through the
362 * file for the beginning of the cabinet (as we also do in cabextract.c).
363 * Note that this limits us to a maximum of one cabinet per. file: the first.
365 * So, in summary: either the code below is wrong, or the rest of fdi.c is
366 * wrong... I cannot imagine that both are correct ;) One of these flaws
367 * should be fixed after determining the behavior on Windows. We ought
368 * to check both FDIIsCabinet and FDICopy for the right behavior.
370 * -gmt
373 /* get basic offset & size info */
374 base_offset = FDI_getoffset(hfdi, hf);
376 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
377 if (pmii) {
378 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
379 PFDI_INT(hfdi)->perf->erfType = 0;
380 PFDI_INT(hfdi)->perf->fError = TRUE;
382 return FALSE;
385 cabsize = FDI_getoffset(hfdi, hf);
387 if ((cabsize == -1) || (base_offset == -1) ||
388 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
389 if (pmii) {
390 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
391 PFDI_INT(hfdi)->perf->erfType = 0;
392 PFDI_INT(hfdi)->perf->fError = TRUE;
394 return FALSE;
397 /* read in the CFHEADER */
398 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
399 if (pmii) {
400 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
401 PFDI_INT(hfdi)->perf->erfType = 0;
402 PFDI_INT(hfdi)->perf->fError = TRUE;
404 return FALSE;
407 /* check basic MSCF signature */
408 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
409 if (pmii) {
410 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
411 PFDI_INT(hfdi)->perf->erfType = 0;
412 PFDI_INT(hfdi)->perf->fError = TRUE;
414 return FALSE;
417 /* get the number of folders */
418 num_folders = EndGetI16(buf+cfhead_NumFolders);
419 if (num_folders == 0) {
420 /* PONDERME: is this really invalid? */
421 WARN("weird cabinet detect failure: no folders in cabinet\n");
422 if (pmii) {
423 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
424 PFDI_INT(hfdi)->perf->erfType = 0;
425 PFDI_INT(hfdi)->perf->fError = TRUE;
427 return FALSE;
430 /* get the number of files */
431 num_files = EndGetI16(buf+cfhead_NumFiles);
432 if (num_files == 0) {
433 /* PONDERME: is this really invalid? */
434 WARN("weird cabinet detect failure: no files in cabinet\n");
435 if (pmii) {
436 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
437 PFDI_INT(hfdi)->perf->erfType = 0;
438 PFDI_INT(hfdi)->perf->fError = TRUE;
440 return FALSE;
443 /* setid */
444 setid = EndGetI16(buf+cfhead_SetID);
446 /* cabinet (set) index */
447 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
449 /* check the header revision */
450 if ((buf[cfhead_MajorVersion] > 1) ||
451 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
453 WARN("cabinet format version > 1.3\n");
454 if (pmii) {
455 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
456 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
457 PFDI_INT(hfdi)->perf->fError = TRUE;
459 return FALSE;
462 /* pull the flags out */
463 flags = EndGetI16(buf+cfhead_Flags);
465 /* read the reserved-sizes part of header, if present */
466 if (flags & cfheadRESERVE_PRESENT) {
467 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
468 ERR("bunk reserve-sizes?\n");
469 if (pmii) {
470 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
471 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
472 PFDI_INT(hfdi)->perf->fError = TRUE;
474 return FALSE;
477 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
478 if (pmii) pmii->header_resv = header_resv;
479 folder_resv = buf[cfheadext_FolderReserved];
480 if (pmii) pmii->folder_resv = folder_resv;
481 block_resv = buf[cfheadext_DataReserved];
482 if (pmii) pmii->block_resv = block_resv;
484 if (header_resv > 60000) {
485 WARN("WARNING; header reserved space > 60000\n");
488 /* skip the reserved header */
489 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
490 ERR("seek failure: header_resv\n");
491 if (pmii) {
492 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
493 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
494 PFDI_INT(hfdi)->perf->fError = TRUE;
496 return FALSE;
500 if (flags & cfheadPREV_CABINET) {
501 prevname = FDI_read_string(hfdi, hf, cabsize);
502 if (!prevname) {
503 if (pmii) {
504 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
505 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
506 PFDI_INT(hfdi)->perf->fError = TRUE;
508 return FALSE;
509 } else
510 if (pmii)
511 pmii->prevname = prevname;
512 else
513 PFDI_FREE(hfdi, prevname);
514 previnfo = FDI_read_string(hfdi, hf, cabsize);
515 if (previnfo) {
516 if (pmii)
517 pmii->previnfo = previnfo;
518 else
519 PFDI_FREE(hfdi, previnfo);
523 if (flags & cfheadNEXT_CABINET) {
524 if (pmii)
525 pmii->hasnext = TRUE;
526 nextname = FDI_read_string(hfdi, hf, cabsize);
527 if (!nextname) {
528 if ((flags & cfheadPREV_CABINET) && pmii) {
529 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
530 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
532 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
533 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
534 PFDI_INT(hfdi)->perf->fError = TRUE;
535 return FALSE;
536 } else
537 if (pmii)
538 pmii->nextname = nextname;
539 else
540 PFDI_FREE(hfdi, nextname);
541 nextinfo = FDI_read_string(hfdi, hf, cabsize);
542 if (nextinfo) {
543 if (pmii)
544 pmii->nextinfo = nextinfo;
545 else
546 PFDI_FREE(hfdi, nextinfo);
550 /* we could process the whole cabinet searching for problems;
551 instead lets stop here. Now let's fill out the paperwork */
552 pfdici->cbCabinet = cabsize;
553 pfdici->cFolders = num_folders;
554 pfdici->cFiles = num_files;
555 pfdici->setID = setid;
556 pfdici->iCabinet = cabidx;
557 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
558 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
559 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
560 return TRUE;
563 /***********************************************************************
564 * FDIIsCabinet (CABINET.21)
566 * Informs the caller as to whether or not the provided file handle is
567 * really a cabinet or not, filling out the provided PFDICABINETINFO
568 * structure with information about the cabinet. Brief explanations of
569 * the elements of this structure are available as comments accompanying
570 * its definition in wine's include/fdi.h.
572 * PARAMS
573 * hfdi [I] An HFDI from FDICreate
574 * hf [I] The file handle about which the caller inquires
575 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
576 * be filled out with information about the cabinet
577 * file indicated by hf if, indeed, it is determined
578 * to be a cabinet.
580 * RETURNS
581 * TRUE if the file is a cabinet. The info pointed to by pfdici will
582 * be provided.
583 * FALSE if the file is not a cabinet, or if an error was encountered
584 * while processing the cabinet. The PERF structure provided to
585 * FDICreate can be queried for more error information.
587 * INCLUDES
588 * fdi.c
590 BOOL __cdecl FDIIsCabinet(
591 HFDI hfdi,
592 INT_PTR hf,
593 PFDICABINETINFO pfdici)
595 BOOL rv;
597 TRACE("(hfdi == ^%p, hf == ^%d, pfdici == ^%p)\n", hfdi, hf, pfdici);
599 if (!REALLY_IS_FDI(hfdi)) {
600 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
601 SetLastError(ERROR_INVALID_HANDLE);
602 return FALSE;
605 if (!hf) {
606 ERR("(!hf)!\n");
607 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
608 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
609 PFDI_INT(hfdi)->perf->fError = TRUE; */
610 SetLastError(ERROR_INVALID_HANDLE);
611 return FALSE;
614 if (!pfdici) {
615 ERR("(!pfdici)!\n");
616 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
617 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
618 PFDI_INT(hfdi)->perf->fError = TRUE; */
619 SetLastError(ERROR_BAD_ARGUMENTS);
620 return FALSE;
622 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
624 if (rv)
625 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
627 return rv;
630 /******************************************************************
631 * QTMfdi_initmodel (internal)
633 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
635 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
636 int i;
637 m->shiftsleft = 4;
638 m->entries = n;
639 m->syms = sym;
640 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
641 for (i = 0; i < n; i++) {
642 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
643 m->syms[i].sym = i+s; /* actual symbol */
644 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
646 m->syms[n].cumfreq = 0;
649 /******************************************************************
650 * QTMfdi_init (internal)
652 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
653 unsigned int wndsize = 1 << window;
654 int msz = window * 2, i;
655 cab_ULONG j;
657 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
658 /* if a previously allocated window is big enough, keep it */
659 if (window < 10 || window > 21) return DECR_DATAFORMAT;
660 if (QTM(actual_size) < wndsize) {
661 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
662 QTM(window) = NULL;
664 if (!QTM(window)) {
665 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
666 QTM(actual_size) = wndsize;
668 QTM(window_size) = wndsize;
669 QTM(window_posn) = 0;
671 /* initialize static slot/extrabits tables */
672 for (i = 0, j = 0; i < 27; i++) {
673 CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
674 CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
676 for (i = 0, j = 0; i < 42; i++) {
677 CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
678 CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
681 /* initialize arithmetic coding models */
683 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
685 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
686 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
687 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
688 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
690 /* model 4 depends on table size, ranges from 20 to 24 */
691 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
692 /* model 5 depends on table size, ranges from 20 to 36 */
693 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
694 /* model 6pos depends on table size, ranges from 20 to 42 */
695 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
696 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
698 return DECR_OK;
701 /************************************************************
702 * LZXfdi_init (internal)
704 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
705 cab_ULONG wndsize = 1 << window;
706 int i, j, posn_slots;
708 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
709 /* if a previously allocated window is big enough, keep it */
710 if (window < 15 || window > 21) return DECR_DATAFORMAT;
711 if (LZX(actual_size) < wndsize) {
712 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
713 LZX(window) = NULL;
715 if (!LZX(window)) {
716 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
717 LZX(actual_size) = wndsize;
719 LZX(window_size) = wndsize;
721 /* initialize static tables */
722 for (i=0, j=0; i <= 50; i += 2) {
723 CAB(extra_bits)[i] = CAB(extra_bits)[i+1] = j; /* 0,0,0,0,1,1,2,2,3,3... */
724 if ((i != 0) && (j < 17)) j++; /* 0,0,1,2,3,4...15,16,17,17,17,17... */
726 for (i=0, j=0; i <= 50; i++) {
727 CAB(lzx_position_base)[i] = j; /* 0,1,2,3,4,6,8,12,16,24,32,... */
728 j += 1 << CAB(extra_bits)[i]; /* 1,1,1,1,2,2,4,4,8,8,16,16,32,32,... */
731 /* calculate required position slots */
732 if (window == 20) posn_slots = 42;
733 else if (window == 21) posn_slots = 50;
734 else posn_slots = window << 1;
736 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
738 LZX(R0) = LZX(R1) = LZX(R2) = 1;
739 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
740 LZX(header_read) = 0;
741 LZX(frames_read) = 0;
742 LZX(block_remaining) = 0;
743 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
744 LZX(intel_curpos) = 0;
745 LZX(intel_started) = 0;
746 LZX(window_posn) = 0;
748 /* initialize tables to 0 (because deltas will be applied to them) */
749 for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) LZX(MAINTREE_len)[i] = 0;
750 for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) LZX(LENGTH_len)[i] = 0;
752 return DECR_OK;
755 /****************************************************
756 * NONEfdi_decomp(internal)
758 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
760 if (inlen != outlen) return DECR_ILLEGALDATA;
761 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
762 return DECR_OK;
765 /********************************************************
766 * Ziphuft_free (internal)
768 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
770 register struct Ziphuft *p, *q;
772 /* Go through linked list, freeing from the allocated (t[-1]) address. */
773 p = t;
774 while (p != (struct Ziphuft *)NULL)
776 q = (--p)->v.t;
777 PFDI_FREE(hfdi, p);
778 p = q;
782 /*********************************************************
783 * fdi_Ziphuft_build (internal)
785 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, cab_UWORD *d, cab_UWORD *e,
786 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
788 cab_ULONG a; /* counter for codes of length k */
789 cab_ULONG el; /* length of EOB code (value 256) */
790 cab_ULONG f; /* i repeats in table every f entries */
791 cab_LONG g; /* maximum code length */
792 cab_LONG h; /* table level */
793 register cab_ULONG i; /* counter, current code */
794 register cab_ULONG j; /* counter */
795 register cab_LONG k; /* number of bits in current code */
796 cab_LONG *l; /* stack of bits per table */
797 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
798 register struct Ziphuft *q; /* points to current table */
799 struct Ziphuft r; /* table entry for structure assignment */
800 register cab_LONG w; /* bits before this table == (l * h) */
801 cab_ULONG *xp; /* pointer into x */
802 cab_LONG y; /* number of dummy codes added */
803 cab_ULONG z; /* number of entries in current table */
805 l = ZIP(lx)+1;
807 /* Generate counts for each bit length */
808 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
810 for(i = 0; i < ZIPBMAX+1; ++i)
811 ZIP(c)[i] = 0;
812 p = b; i = n;
815 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
816 } while (--i);
817 if (ZIP(c)[0] == n) /* null input--all zero length codes */
819 *t = (struct Ziphuft *)NULL;
820 *m = 0;
821 return 0;
824 /* Find minimum and maximum length, bound *m by those */
825 for (j = 1; j <= ZIPBMAX; j++)
826 if (ZIP(c)[j])
827 break;
828 k = j; /* minimum code length */
829 if ((cab_ULONG)*m < j)
830 *m = j;
831 for (i = ZIPBMAX; i; i--)
832 if (ZIP(c)[i])
833 break;
834 g = i; /* maximum code length */
835 if ((cab_ULONG)*m > i)
836 *m = i;
838 /* Adjust last length count to fill out codes, if needed */
839 for (y = 1 << j; j < i; j++, y <<= 1)
840 if ((y -= ZIP(c)[j]) < 0)
841 return 2; /* bad input: more codes than bits */
842 if ((y -= ZIP(c)[i]) < 0)
843 return 2;
844 ZIP(c)[i] += y;
846 /* Generate starting offsets LONGo the value table for each length */
847 ZIP(x)[1] = j = 0;
848 p = ZIP(c) + 1; xp = ZIP(x) + 2;
849 while (--i)
850 { /* note that i == g from above */
851 *xp++ = (j += *p++);
854 /* Make a table of values in order of bit lengths */
855 p = b; i = 0;
857 if ((j = *p++) != 0)
858 ZIP(v)[ZIP(x)[j]++] = i;
859 } while (++i < n);
862 /* Generate the Huffman codes and for each, make the table entries */
863 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
864 p = ZIP(v); /* grab values in bit order */
865 h = -1; /* no tables yet--level -1 */
866 w = l[-1] = 0; /* no bits decoded yet */
867 ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */
868 q = (struct Ziphuft *)NULL; /* ditto */
869 z = 0; /* ditto */
871 /* go through the bit lengths (k already is bits in shortest code) */
872 for (; k <= g; k++)
874 a = ZIP(c)[k];
875 while (a--)
877 /* here i is the Huffman code of length k bits for value *p */
878 /* make tables up to required level */
879 while (k > w + l[h])
881 w += l[h++]; /* add bits already decoded */
883 /* compute minimum size table less than or equal to *m bits */
884 z = (z = g - w) > (cab_ULONG)*m ? *m : z; /* upper limit */
885 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
886 { /* too few codes for k-w bit table */
887 f -= a + 1; /* deduct codes from patterns left */
888 xp = ZIP(c) + k;
889 while (++j < z) /* try smaller tables up to z bits */
891 if ((f <<= 1) <= *++xp)
892 break; /* enough codes to use up j bits */
893 f -= *xp; /* else deduct codes from patterns */
896 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
897 j = el - w; /* make EOB code end at table */
898 z = 1 << j; /* table entries for j-bit table */
899 l[h] = j; /* set table size in stack */
901 /* allocate and link in new table */
902 if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
904 if(h)
905 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
906 return 3; /* not enough memory */
908 *t = q + 1; /* link to list for Ziphuft_free() */
909 *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
910 ZIP(u)[h] = ++q; /* table starts after link */
912 /* connect to last table, if there is one */
913 if (h)
915 ZIP(x)[h] = i; /* save pattern for backing up */
916 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
917 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
918 r.v.t = q; /* pointer to this table */
919 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
920 ZIP(u)[h-1][j] = r; /* connect to last table */
924 /* set up table entry in r */
925 r.b = (cab_UBYTE)(k - w);
926 if (p >= ZIP(v) + n)
927 r.e = 99; /* out of values--invalid code */
928 else if (*p < s)
930 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
931 r.v.n = *p++; /* simple code is just the value */
933 else
935 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
936 r.v.n = d[*p++ - s];
939 /* fill code-like entries with r */
940 f = 1 << (k - w);
941 for (j = i >> w; j < z; j += f)
942 q[j] = r;
944 /* backwards increment the k-bit code i */
945 for (j = 1 << (k - 1); i & j; j >>= 1)
946 i ^= j;
947 i ^= j;
949 /* backup over finished tables */
950 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
951 w -= l[--h]; /* don't need to update q */
955 /* return actual size of base table */
956 *m = l[0];
958 /* Return true (1) if we were given an incomplete table */
959 return y != 0 && g != 1;
962 /*********************************************************
963 * fdi_Zipinflate_codes (internal)
965 cab_LONG fdi_Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td,
966 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
968 register cab_ULONG e; /* table entry flag/number of extra bits */
969 cab_ULONG n, d; /* length and index for copy */
970 cab_ULONG w; /* current window position */
971 struct Ziphuft *t; /* pointer to table entry */
972 cab_ULONG ml, md; /* masks for bl and bd bits */
973 register cab_ULONG b; /* bit buffer */
974 register cab_ULONG k; /* number of bits in bit buffer */
976 /* make local copies of globals */
977 b = ZIP(bb); /* initialize bit buffer */
978 k = ZIP(bk);
979 w = ZIP(window_posn); /* initialize window position */
981 /* inflate the coded data */
982 ml = Zipmask[bl]; /* precompute masks for speed */
983 md = Zipmask[bd];
985 for(;;)
987 ZIPNEEDBITS((cab_ULONG)bl)
988 if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16)
991 if (e == 99)
992 return 1;
993 ZIPDUMPBITS(t->b)
994 e -= 16;
995 ZIPNEEDBITS(e)
996 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
997 ZIPDUMPBITS(t->b)
998 if (e == 16) /* then it's a literal */
999 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
1000 else /* it's an EOB or a length */
1002 /* exit if end of block */
1003 if(e == 15)
1004 break;
1006 /* get length of block to copy */
1007 ZIPNEEDBITS(e)
1008 n = t->v.n + ((cab_ULONG)b & Zipmask[e]);
1009 ZIPDUMPBITS(e);
1011 /* decode distance of block to copy */
1012 ZIPNEEDBITS((cab_ULONG)bd)
1013 if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16)
1014 do {
1015 if (e == 99)
1016 return 1;
1017 ZIPDUMPBITS(t->b)
1018 e -= 16;
1019 ZIPNEEDBITS(e)
1020 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
1021 ZIPDUMPBITS(t->b)
1022 ZIPNEEDBITS(e)
1023 d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]);
1024 ZIPDUMPBITS(e)
1027 n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
1030 CAB(outbuf)[w++] = CAB(outbuf)[d++];
1031 } while (--e);
1032 } while (n);
1036 /* restore the globals from the locals */
1037 ZIP(window_posn) = w; /* restore global window pointer */
1038 ZIP(bb) = b; /* restore global bit buffer */
1039 ZIP(bk) = k;
1041 /* done */
1042 return 0;
1045 /***********************************************************
1046 * Zipinflate_stored (internal)
1048 static cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1049 /* "decompress" an inflated type 0 (stored) block. */
1051 cab_ULONG n; /* number of bytes in block */
1052 cab_ULONG w; /* current window position */
1053 register cab_ULONG b; /* bit buffer */
1054 register cab_ULONG k; /* number of bits in bit buffer */
1056 /* make local copies of globals */
1057 b = ZIP(bb); /* initialize bit buffer */
1058 k = ZIP(bk);
1059 w = ZIP(window_posn); /* initialize window position */
1061 /* go to byte boundary */
1062 n = k & 7;
1063 ZIPDUMPBITS(n);
1065 /* get the length and its complement */
1066 ZIPNEEDBITS(16)
1067 n = ((cab_ULONG)b & 0xffff);
1068 ZIPDUMPBITS(16)
1069 ZIPNEEDBITS(16)
1070 if (n != (cab_ULONG)((~b) & 0xffff))
1071 return 1; /* error in compressed data */
1072 ZIPDUMPBITS(16)
1074 /* read and output the compressed data */
1075 while(n--)
1077 ZIPNEEDBITS(8)
1078 CAB(outbuf)[w++] = (cab_UBYTE)b;
1079 ZIPDUMPBITS(8)
1082 /* restore the globals from the locals */
1083 ZIP(window_posn) = w; /* restore global window pointer */
1084 ZIP(bb) = b; /* restore global bit buffer */
1085 ZIP(bk) = k;
1086 return 0;
1089 /******************************************************
1090 * fdi_Zipinflate_fixed (internal)
1092 static cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1094 struct Ziphuft *fixed_tl;
1095 struct Ziphuft *fixed_td;
1096 cab_LONG fixed_bl, fixed_bd;
1097 cab_LONG i; /* temporary variable */
1098 cab_ULONG *l;
1100 l = ZIP(ll);
1102 /* literal table */
1103 for(i = 0; i < 144; i++)
1104 l[i] = 8;
1105 for(; i < 256; i++)
1106 l[i] = 9;
1107 for(; i < 280; i++)
1108 l[i] = 7;
1109 for(; i < 288; i++) /* make a complete, but wrong code set */
1110 l[i] = 8;
1111 fixed_bl = 7;
1112 if((i = fdi_Ziphuft_build(l, 288, 257, (cab_UWORD *) Zipcplens,
1113 (cab_UWORD *) Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1114 return i;
1116 /* distance table */
1117 for(i = 0; i < 30; i++) /* make an incomplete code set */
1118 l[i] = 5;
1119 fixed_bd = 5;
1120 if((i = fdi_Ziphuft_build(l, 30, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
1121 &fixed_td, &fixed_bd, decomp_state)) > 1)
1123 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1124 return i;
1127 /* decompress until an end-of-block code */
1128 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1130 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1131 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1132 return i;
1135 /**************************************************************
1136 * fdi_Zipinflate_dynamic (internal)
1138 static cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1139 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1141 cab_LONG i; /* temporary variables */
1142 cab_ULONG j;
1143 cab_ULONG *ll;
1144 cab_ULONG l; /* last length */
1145 cab_ULONG m; /* mask for bit lengths table */
1146 cab_ULONG n; /* number of lengths to get */
1147 struct Ziphuft *tl; /* literal/length code table */
1148 struct Ziphuft *td; /* distance code table */
1149 cab_LONG bl; /* lookup bits for tl */
1150 cab_LONG bd; /* lookup bits for td */
1151 cab_ULONG nb; /* number of bit length codes */
1152 cab_ULONG nl; /* number of literal/length codes */
1153 cab_ULONG nd; /* number of distance codes */
1154 register cab_ULONG b; /* bit buffer */
1155 register cab_ULONG k; /* number of bits in bit buffer */
1157 /* make local bit buffer */
1158 b = ZIP(bb);
1159 k = ZIP(bk);
1160 ll = ZIP(ll);
1162 /* read in table lengths */
1163 ZIPNEEDBITS(5)
1164 nl = 257 + ((cab_ULONG)b & 0x1f); /* number of literal/length codes */
1165 ZIPDUMPBITS(5)
1166 ZIPNEEDBITS(5)
1167 nd = 1 + ((cab_ULONG)b & 0x1f); /* number of distance codes */
1168 ZIPDUMPBITS(5)
1169 ZIPNEEDBITS(4)
1170 nb = 4 + ((cab_ULONG)b & 0xf); /* number of bit length codes */
1171 ZIPDUMPBITS(4)
1172 if(nl > 288 || nd > 32)
1173 return 1; /* bad lengths */
1175 /* read in bit-length-code lengths */
1176 for(j = 0; j < nb; j++)
1178 ZIPNEEDBITS(3)
1179 ll[Zipborder[j]] = (cab_ULONG)b & 7;
1180 ZIPDUMPBITS(3)
1182 for(; j < 19; j++)
1183 ll[Zipborder[j]] = 0;
1185 /* build decoding table for trees--single level, 7 bit lookup */
1186 bl = 7;
1187 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1189 if(i == 1)
1190 fdi_Ziphuft_free(CAB(hfdi), tl);
1191 return i; /* incomplete code set */
1194 /* read in literal and distance code lengths */
1195 n = nl + nd;
1196 m = Zipmask[bl];
1197 i = l = 0;
1198 while((cab_ULONG)i < n)
1200 ZIPNEEDBITS((cab_ULONG)bl)
1201 j = (td = tl + ((cab_ULONG)b & m))->b;
1202 ZIPDUMPBITS(j)
1203 j = td->v.n;
1204 if (j < 16) /* length of code in bits (0..15) */
1205 ll[i++] = l = j; /* save last length in l */
1206 else if (j == 16) /* repeat last length 3 to 6 times */
1208 ZIPNEEDBITS(2)
1209 j = 3 + ((cab_ULONG)b & 3);
1210 ZIPDUMPBITS(2)
1211 if((cab_ULONG)i + j > n)
1212 return 1;
1213 while (j--)
1214 ll[i++] = l;
1216 else if (j == 17) /* 3 to 10 zero length codes */
1218 ZIPNEEDBITS(3)
1219 j = 3 + ((cab_ULONG)b & 7);
1220 ZIPDUMPBITS(3)
1221 if ((cab_ULONG)i + j > n)
1222 return 1;
1223 while (j--)
1224 ll[i++] = 0;
1225 l = 0;
1227 else /* j == 18: 11 to 138 zero length codes */
1229 ZIPNEEDBITS(7)
1230 j = 11 + ((cab_ULONG)b & 0x7f);
1231 ZIPDUMPBITS(7)
1232 if ((cab_ULONG)i + j > n)
1233 return 1;
1234 while (j--)
1235 ll[i++] = 0;
1236 l = 0;
1240 /* free decoding table for trees */
1241 fdi_Ziphuft_free(CAB(hfdi), tl);
1243 /* restore the global bit buffer */
1244 ZIP(bb) = b;
1245 ZIP(bk) = k;
1247 /* build the decoding tables for literal/length and distance codes */
1248 bl = ZIPLBITS;
1249 if((i = fdi_Ziphuft_build(ll, nl, 257, (cab_UWORD *) Zipcplens, (cab_UWORD *) Zipcplext,
1250 &tl, &bl, decomp_state)) != 0)
1252 if(i == 1)
1253 fdi_Ziphuft_free(CAB(hfdi), tl);
1254 return i; /* incomplete code set */
1256 bd = ZIPDBITS;
1257 fdi_Ziphuft_build(ll + nl, nd, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
1258 &td, &bd, decomp_state);
1260 /* decompress until an end-of-block code */
1261 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1262 return 1;
1264 /* free the decoding tables, return */
1265 fdi_Ziphuft_free(CAB(hfdi), tl);
1266 fdi_Ziphuft_free(CAB(hfdi), td);
1267 return 0;
1270 /*****************************************************
1271 * fdi_Zipinflate_block (internal)
1273 static cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1274 { /* decompress an inflated block */
1275 cab_ULONG t; /* block type */
1276 register cab_ULONG b; /* bit buffer */
1277 register cab_ULONG k; /* number of bits in bit buffer */
1279 /* make local bit buffer */
1280 b = ZIP(bb);
1281 k = ZIP(bk);
1283 /* read in last block bit */
1284 ZIPNEEDBITS(1)
1285 *e = (cab_LONG)b & 1;
1286 ZIPDUMPBITS(1)
1288 /* read in block type */
1289 ZIPNEEDBITS(2)
1290 t = (cab_ULONG)b & 3;
1291 ZIPDUMPBITS(2)
1293 /* restore the global bit buffer */
1294 ZIP(bb) = b;
1295 ZIP(bk) = k;
1297 /* inflate that block type */
1298 if(t == 2)
1299 return fdi_Zipinflate_dynamic(decomp_state);
1300 if(t == 0)
1301 return fdi_Zipinflate_stored(decomp_state);
1302 if(t == 1)
1303 return fdi_Zipinflate_fixed(decomp_state);
1304 /* bad block type */
1305 return 2;
1308 /****************************************************
1309 * ZIPfdi_decomp(internal)
1311 static int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1313 cab_LONG e; /* last block flag */
1315 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1317 ZIP(inpos) = CAB(inbuf);
1318 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1319 if(outlen > ZIPWSIZE)
1320 return DECR_DATAFORMAT;
1322 /* CK = Chris Kirmse, official Microsoft purloiner */
1323 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1324 return DECR_ILLEGALDATA;
1325 ZIP(inpos) += 2;
1327 do {
1328 if(fdi_Zipinflate_block(&e, decomp_state))
1329 return DECR_ILLEGALDATA;
1330 } while(!e);
1332 /* return success */
1333 return DECR_OK;
1336 /*******************************************************************
1337 * QTMfdi_decomp(internal)
1339 static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1341 cab_UBYTE *inpos = CAB(inbuf);
1342 cab_UBYTE *window = QTM(window);
1343 cab_UBYTE *runsrc, *rundest;
1345 cab_ULONG window_posn = QTM(window_posn);
1346 cab_ULONG window_size = QTM(window_size);
1348 /* used by bitstream macros */
1349 register int bitsleft, bitrun, bitsneed;
1350 register cab_ULONG bitbuf;
1352 /* used by GET_SYMBOL */
1353 cab_ULONG range;
1354 cab_UWORD symf;
1355 int i;
1357 int extra, togo = outlen, match_length = 0, copy_length;
1358 cab_UBYTE selector, sym;
1359 cab_ULONG match_offset = 0;
1361 cab_UWORD H = 0xFFFF, L = 0, C;
1363 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1365 /* read initial value of C */
1366 Q_INIT_BITSTREAM;
1367 Q_READ_BITS(C, 16);
1369 /* apply 2^x-1 mask */
1370 window_posn &= window_size - 1;
1371 /* runs can't straddle the window wraparound */
1372 if ((window_posn + togo) > window_size) {
1373 TRACE("straddled run\n");
1374 return DECR_DATAFORMAT;
1377 while (togo > 0) {
1378 GET_SYMBOL(model7, selector);
1379 switch (selector) {
1380 case 0:
1381 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1382 break;
1383 case 1:
1384 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1385 break;
1386 case 2:
1387 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1388 break;
1389 case 3:
1390 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1391 break;
1393 case 4:
1394 /* selector 4 = fixed length of 3 */
1395 GET_SYMBOL(model4, sym);
1396 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1397 match_offset = CAB(q_position_base)[sym] + extra + 1;
1398 match_length = 3;
1399 break;
1401 case 5:
1402 /* selector 5 = fixed length of 4 */
1403 GET_SYMBOL(model5, sym);
1404 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1405 match_offset = CAB(q_position_base)[sym] + extra + 1;
1406 match_length = 4;
1407 break;
1409 case 6:
1410 /* selector 6 = variable length */
1411 GET_SYMBOL(model6len, sym);
1412 Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1413 match_length = CAB(q_length_base)[sym] + extra + 5;
1414 GET_SYMBOL(model6pos, sym);
1415 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1416 match_offset = CAB(q_position_base)[sym] + extra + 1;
1417 break;
1419 default:
1420 TRACE("Selector is bogus\n");
1421 return DECR_ILLEGALDATA;
1424 /* if this is a match */
1425 if (selector >= 4) {
1426 rundest = window + window_posn;
1427 togo -= match_length;
1429 /* copy any wrapped around source data */
1430 if (window_posn >= match_offset) {
1431 /* no wrap */
1432 runsrc = rundest - match_offset;
1433 } else {
1434 runsrc = rundest + (window_size - match_offset);
1435 copy_length = match_offset - window_posn;
1436 if (copy_length < match_length) {
1437 match_length -= copy_length;
1438 window_posn += copy_length;
1439 while (copy_length-- > 0) *rundest++ = *runsrc++;
1440 runsrc = window;
1443 window_posn += match_length;
1445 /* copy match data - no worries about destination wraps */
1446 while (match_length-- > 0) *rundest++ = *runsrc++;
1448 } /* while (togo > 0) */
1450 if (togo != 0) {
1451 TRACE("Frame overflow, this_run = %d\n", togo);
1452 return DECR_ILLEGALDATA;
1455 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1456 outlen, outlen);
1458 QTM(window_posn) = window_posn;
1459 return DECR_OK;
1462 /************************************************************
1463 * fdi_lzx_read_lens (internal)
1465 static int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1466 fdi_decomp_state *decomp_state) {
1467 cab_ULONG i,j, x,y;
1468 int z;
1470 register cab_ULONG bitbuf = lb->bb;
1471 register int bitsleft = lb->bl;
1472 cab_UBYTE *inpos = lb->ip;
1473 cab_UWORD *hufftbl;
1475 for (x = 0; x < 20; x++) {
1476 READ_BITS(y, 4);
1477 LENTABLE(PRETREE)[x] = y;
1479 BUILD_TABLE(PRETREE);
1481 for (x = first; x < last; ) {
1482 READ_HUFFSYM(PRETREE, z);
1483 if (z == 17) {
1484 READ_BITS(y, 4); y += 4;
1485 while (y--) lens[x++] = 0;
1487 else if (z == 18) {
1488 READ_BITS(y, 5); y += 20;
1489 while (y--) lens[x++] = 0;
1491 else if (z == 19) {
1492 READ_BITS(y, 1); y += 4;
1493 READ_HUFFSYM(PRETREE, z);
1494 z = lens[x] - z; if (z < 0) z += 17;
1495 while (y--) lens[x++] = z;
1497 else {
1498 z = lens[x] - z; if (z < 0) z += 17;
1499 lens[x++] = z;
1503 lb->bb = bitbuf;
1504 lb->bl = bitsleft;
1505 lb->ip = inpos;
1506 return 0;
1509 /*******************************************************
1510 * LZXfdi_decomp(internal)
1512 static int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1513 cab_UBYTE *inpos = CAB(inbuf);
1514 cab_UBYTE *endinp = inpos + inlen;
1515 cab_UBYTE *window = LZX(window);
1516 cab_UBYTE *runsrc, *rundest;
1517 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1519 cab_ULONG window_posn = LZX(window_posn);
1520 cab_ULONG window_size = LZX(window_size);
1521 cab_ULONG R0 = LZX(R0);
1522 cab_ULONG R1 = LZX(R1);
1523 cab_ULONG R2 = LZX(R2);
1525 register cab_ULONG bitbuf;
1526 register int bitsleft;
1527 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1528 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1530 int togo = outlen, this_run, main_element, aligned_bits;
1531 int match_length, copy_length, length_footer, extra, verbatim_bits;
1533 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1535 INIT_BITSTREAM;
1537 /* read header if necessary */
1538 if (!LZX(header_read)) {
1539 i = j = 0;
1540 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1541 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1542 LZX(header_read) = 1;
1545 /* main decoding loop */
1546 while (togo > 0) {
1547 /* last block finished, new block expected */
1548 if (LZX(block_remaining) == 0) {
1549 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1550 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1551 INIT_BITSTREAM;
1554 READ_BITS(LZX(block_type), 3);
1555 READ_BITS(i, 16);
1556 READ_BITS(j, 8);
1557 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1559 switch (LZX(block_type)) {
1560 case LZX_BLOCKTYPE_ALIGNED:
1561 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1562 BUILD_TABLE(ALIGNED);
1563 /* rest of aligned header is same as verbatim */
1565 case LZX_BLOCKTYPE_VERBATIM:
1566 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1567 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1568 BUILD_TABLE(MAINTREE);
1569 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1571 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1572 BUILD_TABLE(LENGTH);
1573 break;
1575 case LZX_BLOCKTYPE_UNCOMPRESSED:
1576 LZX(intel_started) = 1; /* because we can't assume otherwise */
1577 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1578 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1579 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1580 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1581 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1582 break;
1584 default:
1585 return DECR_ILLEGALDATA;
1589 /* buffer exhaustion check */
1590 if (inpos > endinp) {
1591 /* it's possible to have a file where the next run is less than
1592 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1593 * in building the tables will exhaust the buffer, so we should
1594 * allow for this, but not allow those accidentally read bits to
1595 * be used (so we check that there are at least 16 bits
1596 * remaining - in this boundary case they aren't really part of
1597 * the compressed data)
1599 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1602 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1603 if (this_run > togo) this_run = togo;
1604 togo -= this_run;
1605 LZX(block_remaining) -= this_run;
1607 /* apply 2^x-1 mask */
1608 window_posn &= window_size - 1;
1609 /* runs can't straddle the window wraparound */
1610 if ((window_posn + this_run) > window_size)
1611 return DECR_DATAFORMAT;
1613 switch (LZX(block_type)) {
1615 case LZX_BLOCKTYPE_VERBATIM:
1616 while (this_run > 0) {
1617 READ_HUFFSYM(MAINTREE, main_element);
1619 if (main_element < LZX_NUM_CHARS) {
1620 /* literal: 0 to LZX_NUM_CHARS-1 */
1621 window[window_posn++] = main_element;
1622 this_run--;
1624 else {
1625 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1626 main_element -= LZX_NUM_CHARS;
1628 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1629 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1630 READ_HUFFSYM(LENGTH, length_footer);
1631 match_length += length_footer;
1633 match_length += LZX_MIN_MATCH;
1635 match_offset = main_element >> 3;
1637 if (match_offset > 2) {
1638 /* not repeated offset */
1639 if (match_offset != 3) {
1640 extra = CAB(extra_bits)[match_offset];
1641 READ_BITS(verbatim_bits, extra);
1642 match_offset = CAB(lzx_position_base)[match_offset]
1643 - 2 + verbatim_bits;
1645 else {
1646 match_offset = 1;
1649 /* update repeated offset LRU queue */
1650 R2 = R1; R1 = R0; R0 = match_offset;
1652 else if (match_offset == 0) {
1653 match_offset = R0;
1655 else if (match_offset == 1) {
1656 match_offset = R1;
1657 R1 = R0; R0 = match_offset;
1659 else /* match_offset == 2 */ {
1660 match_offset = R2;
1661 R2 = R0; R0 = match_offset;
1664 rundest = window + window_posn;
1665 this_run -= match_length;
1667 /* copy any wrapped around source data */
1668 if (window_posn >= match_offset) {
1669 /* no wrap */
1670 runsrc = rundest - match_offset;
1671 } else {
1672 runsrc = rundest + (window_size - match_offset);
1673 copy_length = match_offset - window_posn;
1674 if (copy_length < match_length) {
1675 match_length -= copy_length;
1676 window_posn += copy_length;
1677 while (copy_length-- > 0) *rundest++ = *runsrc++;
1678 runsrc = window;
1681 window_posn += match_length;
1683 /* copy match data - no worries about destination wraps */
1684 while (match_length-- > 0) *rundest++ = *runsrc++;
1687 break;
1689 case LZX_BLOCKTYPE_ALIGNED:
1690 while (this_run > 0) {
1691 READ_HUFFSYM(MAINTREE, main_element);
1693 if (main_element < LZX_NUM_CHARS) {
1694 /* literal: 0 to LZX_NUM_CHARS-1 */
1695 window[window_posn++] = main_element;
1696 this_run--;
1698 else {
1699 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1700 main_element -= LZX_NUM_CHARS;
1702 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1703 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1704 READ_HUFFSYM(LENGTH, length_footer);
1705 match_length += length_footer;
1707 match_length += LZX_MIN_MATCH;
1709 match_offset = main_element >> 3;
1711 if (match_offset > 2) {
1712 /* not repeated offset */
1713 extra = CAB(extra_bits)[match_offset];
1714 match_offset = CAB(lzx_position_base)[match_offset] - 2;
1715 if (extra > 3) {
1716 /* verbatim and aligned bits */
1717 extra -= 3;
1718 READ_BITS(verbatim_bits, extra);
1719 match_offset += (verbatim_bits << 3);
1720 READ_HUFFSYM(ALIGNED, aligned_bits);
1721 match_offset += aligned_bits;
1723 else if (extra == 3) {
1724 /* aligned bits only */
1725 READ_HUFFSYM(ALIGNED, aligned_bits);
1726 match_offset += aligned_bits;
1728 else if (extra > 0) { /* extra==1, extra==2 */
1729 /* verbatim bits only */
1730 READ_BITS(verbatim_bits, extra);
1731 match_offset += verbatim_bits;
1733 else /* extra == 0 */ {
1734 /* ??? */
1735 match_offset = 1;
1738 /* update repeated offset LRU queue */
1739 R2 = R1; R1 = R0; R0 = match_offset;
1741 else if (match_offset == 0) {
1742 match_offset = R0;
1744 else if (match_offset == 1) {
1745 match_offset = R1;
1746 R1 = R0; R0 = match_offset;
1748 else /* match_offset == 2 */ {
1749 match_offset = R2;
1750 R2 = R0; R0 = match_offset;
1753 rundest = window + window_posn;
1754 this_run -= match_length;
1756 /* copy any wrapped around source data */
1757 if (window_posn >= match_offset) {
1758 /* no wrap */
1759 runsrc = rundest - match_offset;
1760 } else {
1761 runsrc = rundest + (window_size - match_offset);
1762 copy_length = match_offset - window_posn;
1763 if (copy_length < match_length) {
1764 match_length -= copy_length;
1765 window_posn += copy_length;
1766 while (copy_length-- > 0) *rundest++ = *runsrc++;
1767 runsrc = window;
1770 window_posn += match_length;
1772 /* copy match data - no worries about destination wraps */
1773 while (match_length-- > 0) *rundest++ = *runsrc++;
1776 break;
1778 case LZX_BLOCKTYPE_UNCOMPRESSED:
1779 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1780 memcpy(window + window_posn, inpos, (size_t) this_run);
1781 inpos += this_run; window_posn += this_run;
1782 break;
1784 default:
1785 return DECR_ILLEGALDATA; /* might as well */
1791 if (togo != 0) return DECR_ILLEGALDATA;
1792 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1793 outlen, (size_t) outlen);
1795 LZX(window_posn) = window_posn;
1796 LZX(R0) = R0;
1797 LZX(R1) = R1;
1798 LZX(R2) = R2;
1800 /* intel E8 decoding */
1801 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1802 if (outlen <= 6 || !LZX(intel_started)) {
1803 LZX(intel_curpos) += outlen;
1805 else {
1806 cab_UBYTE *data = CAB(outbuf);
1807 cab_UBYTE *dataend = data + outlen - 10;
1808 cab_LONG curpos = LZX(intel_curpos);
1809 cab_LONG filesize = LZX(intel_filesize);
1810 cab_LONG abs_off, rel_off;
1812 LZX(intel_curpos) = curpos + outlen;
1814 while (data < dataend) {
1815 if (*data++ != 0xE8) { curpos++; continue; }
1816 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1817 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1818 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1819 data[0] = (cab_UBYTE) rel_off;
1820 data[1] = (cab_UBYTE) (rel_off >> 8);
1821 data[2] = (cab_UBYTE) (rel_off >> 16);
1822 data[3] = (cab_UBYTE) (rel_off >> 24);
1824 data += 4;
1825 curpos += 5;
1829 return DECR_OK;
1832 /**********************************************************
1833 * fdi_decomp (internal)
1835 * Decompress the requested number of bytes. If savemode is zero,
1836 * do not save the output anywhere, just plow through blocks until we
1837 * reach the specified (uncompressed) distance from the starting point,
1838 * and remember the position of the cabfile pointer (and which cabfile)
1839 * after we are done; otherwise, save the data out to CAB(filehf),
1840 * decompressing the requested number of bytes and writing them out. This
1841 * is also where we jump to additional cabinets in the case of split
1842 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1844 static int fdi_decomp(struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
1845 char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
1847 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
1848 cab_UBYTE buf[cfdata_SIZEOF], *data;
1849 cab_UWORD inlen, len, outlen, cando;
1850 cab_ULONG cksum;
1851 cab_LONG err;
1852 fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
1854 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
1856 while (bytes > 0) {
1857 /* cando = the max number of bytes we can do */
1858 cando = CAB(outlen);
1859 if (cando > bytes) cando = bytes;
1861 /* if cando != 0 */
1862 if (cando && savemode)
1863 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
1865 CAB(outpos) += cando;
1866 CAB(outlen) -= cando;
1867 bytes -= cando; if (!bytes) break;
1869 /* we only get here if we emptied the output buffer */
1871 /* read data header + data */
1872 inlen = outlen = 0;
1873 while (outlen == 0) {
1874 /* read the block header, skip the reserved part */
1875 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
1876 return DECR_INPUT;
1878 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
1879 return DECR_INPUT;
1881 /* we shouldn't get blocks over CAB_INPUTMAX in size */
1882 data = CAB(inbuf) + inlen;
1883 len = EndGetI16(buf+cfdata_CompressedSize);
1884 inlen += len;
1885 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
1886 if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
1887 return DECR_INPUT;
1889 /* clear two bytes after read-in data */
1890 data[len+1] = data[len+2] = 0;
1892 /* perform checksum test on the block (if one is stored) */
1893 cksum = EndGetI32(buf+cfdata_CheckSum);
1894 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
1895 return DECR_CHECKSUM; /* checksum is wrong */
1897 outlen = EndGetI16(buf+cfdata_UncompressedSize);
1899 /* outlen=0 means this block was the last contiguous part
1900 of a split block, continued in the next cabinet */
1901 if (outlen == 0) {
1902 int pathlen, filenamelen, idx, i, cabhf;
1903 char fullpath[MAX_PATH], userpath[256];
1904 FDINOTIFICATION fdin;
1905 FDICABINETINFO fdici;
1906 char emptystring = '\0';
1907 cab_UBYTE buf2[64];
1908 int success = FALSE;
1909 struct fdi_folder *fol = NULL, *linkfol = NULL;
1910 struct fdi_file *file = NULL, *linkfile = NULL;
1912 tryanothercab:
1914 /* set up the next decomp_state... */
1915 if (!(cab->next)) {
1916 if (!cab->mii.hasnext) return DECR_INPUT;
1918 if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
1919 return DECR_NOMEMORY;
1921 ZeroMemory(cab->next, sizeof(fdi_decomp_state));
1923 /* copy pszCabPath to userpath */
1924 ZeroMemory(userpath, 256);
1925 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
1926 if (pathlen) {
1927 if (pathlen < 256) {
1928 for (i = 0; i <= pathlen; i++)
1929 userpath[i] = pszCabPath[i];
1930 } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
1933 /* initial fdintNEXT_CABINET notification */
1934 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1935 fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
1936 fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
1937 fdin.psz3 = &userpath[0];
1938 fdin.fdie = FDIERROR_NONE;
1939 fdin.pv = pvUser;
1941 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1943 do {
1945 pathlen = (userpath) ? strlen(userpath) : 0;
1946 filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
1948 /* slight overestimation here to save CPU cycles in the developer's brain */
1949 if ((pathlen + filenamelen + 3) > MAX_PATH) {
1950 ERR("MAX_PATH exceeded.\n");
1951 return DECR_ILLEGALDATA;
1954 /* paste the path and filename together */
1955 idx = 0;
1956 if (pathlen) {
1957 for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
1958 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
1960 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
1961 fullpath[idx] = '\0';
1963 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
1965 /* try to get a handle to the cabfile */
1966 cabhf = PFDI_OPEN(CAB(hfdi), fullpath, 32768, _S_IREAD | _S_IWRITE);
1967 if (cabhf == -1) {
1968 /* no file. allow the user to try again */
1969 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
1970 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1971 continue;
1974 if (cabhf == 0) {
1975 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
1976 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
1977 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1978 continue;
1981 /* check if it's really a cabfile. Note that this doesn't implement the bug */
1982 if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
1983 WARN("FDIIsCabinet failed.\n");
1984 PFDI_CLOSE(CAB(hfdi), cabhf);
1985 fdin.fdie = FDIERROR_NOT_A_CABINET;
1986 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1987 continue;
1990 if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
1991 WARN("Wrong Cabinet.\n");
1992 PFDI_CLOSE(CAB(hfdi), cabhf);
1993 fdin.fdie = FDIERROR_WRONG_CABINET;
1994 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1995 continue;
1998 break;
2000 } while (1);
2002 /* cabinet notification */
2003 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2004 fdin.setID = fdici.setID;
2005 fdin.iCabinet = fdici.iCabinet;
2006 fdin.pv = pvUser;
2007 fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2008 fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2009 fdin.psz3 = pszCabPath;
2011 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2013 cab->next->setID = fdici.setID;
2014 cab->next->iCabinet = fdici.iCabinet;
2015 cab->next->hfdi = CAB(hfdi);
2016 cab->next->filehf = CAB(filehf);
2017 cab->next->cabhf = cabhf;
2018 cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2020 cab = cab->next; /* advance to the next cabinet */
2022 /* read folders */
2023 for (i = 0; i < fdici.cFolders; i++) {
2024 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF)
2025 return DECR_INPUT;
2027 if (cab->mii.folder_resv > 0)
2028 PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2030 fol = (struct fdi_folder *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2031 if (!fol) {
2032 ERR("out of memory!\n");
2033 return DECR_NOMEMORY;
2035 ZeroMemory(fol, sizeof(struct fdi_folder));
2036 if (!(cab->firstfol)) cab->firstfol = fol;
2038 fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2039 fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2040 fol->comp_type = EndGetI16(buf2+cffold_CompType);
2042 if (linkfol)
2043 linkfol->next = fol;
2044 linkfol = fol;
2047 /* read files */
2048 for (i = 0; i < fdici.cFiles; i++) {
2049 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2050 return DECR_INPUT;
2052 file = (struct fdi_file *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2053 if (!file) {
2054 ERR("out of memory!\n");
2055 return DECR_NOMEMORY;
2057 ZeroMemory(file, sizeof(struct fdi_file));
2058 if (!(cab->firstfile)) cab->firstfile = file;
2060 file->length = EndGetI32(buf2+cffile_UncompressedSize);
2061 file->offset = EndGetI32(buf2+cffile_FolderOffset);
2062 file->index = EndGetI16(buf2+cffile_FolderIndex);
2063 file->time = EndGetI16(buf2+cffile_Time);
2064 file->date = EndGetI16(buf2+cffile_Date);
2065 file->attribs = EndGetI16(buf2+cffile_Attribs);
2066 file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2068 if (!file->filename) return DECR_INPUT;
2070 if (linkfile)
2071 linkfile->next = file;
2072 linkfile = file;
2075 } else
2076 cab = cab->next; /* advance to the next cabinet */
2078 /* iterate files -- if we encounter the continued file, process it --
2079 otherwise, jump to the label above and keep looking */
2081 for (file = cab->firstfile; (file); file = file->next) {
2082 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2083 /* check to ensure a real match */
2084 if (strcasecmp(fi->filename, file->filename) == 0) {
2085 success = TRUE;
2086 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2087 return DECR_INPUT;
2088 break;
2092 if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2093 "Wrong Cabinet" notification? */
2097 /* decompress block */
2098 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2099 return err;
2100 CAB(outlen) = outlen;
2101 CAB(outpos) = CAB(outbuf);
2104 CAB(decomp_cab) = cab;
2105 return DECR_OK;
2108 /***********************************************************************
2109 * FDICopy (CABINET.22)
2111 * Iterates through the files in the Cabinet file indicated by name and
2112 * file-location. May chain forward to additional cabinets (typically
2113 * only one) if files which begin in this Cabinet are continued in another
2114 * cabinet. For each file which is partially contained in this cabinet,
2115 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2116 * notification to the pfnfdin callback. For each file which begins in
2117 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2118 * callback, and the file is optionally decompressed and saved to disk.
2119 * Notification is not provided for files which are not at least partially
2120 * contained in the specified cabinet file.
2122 * See below for a thorough explanation of the various notification
2123 * callbacks.
2125 * PARAMS
2126 * hfdi [I] An HFDI from FDICreate
2127 * pszCabinet [I] C-style string containing the filename of the cabinet
2128 * pszCabPath [I] C-style string containing the file path of the cabinet
2129 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2130 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2131 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2132 * value: NULL.
2133 * pvUser [I] arbitrary void * value which is passed to callbacks.
2135 * RETURNS
2136 * TRUE if successful.
2137 * FALSE if unsuccessful (error information is provided in the ERF structure
2138 * associated with the provided decompression handle by FDICreate).
2140 * CALLBACKS
2142 * Two pointers to callback functions are provided as parameters to FDICopy:
2143 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2144 * types are as follows:
2146 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2147 * PFDINOTIFICATION pfdin );
2149 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2151 * You can create functions of this type using the FNFDINOTIFY() and
2152 * FNFDIDECRYPT() macros, respectively. For example:
2154 * FNFDINOTIFY(mycallback) {
2155 * / * use variables fdint and pfdin to process notification * /
2158 * The second callback, which could be used for decrypting encrypted data,
2159 * is not used at all.
2161 * Each notification informs the user of some event which has occurred during
2162 * decompression of the cabinet file; each notification is also an opportunity
2163 * for the callee to abort decompression. The information provided to the
2164 * callback and the meaning of the callback's return value vary drastically
2165 * across the various types of notification. The type of notification is the
2166 * fdint parameter; all other information is provided to the callback in
2167 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2168 * pfdin. The only part of that structure which is assigned for every callback
2169 * is the pv element, which contains the arbitrary value which was passed to
2170 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2171 * is highly dependent on fdint).
2173 * If you encounter unknown notifications, you should return zero if you want
2174 * decompression to continue (or -1 to abort). All strings used in the
2175 * callbacks are regular C-style strings. Detailed descriptions of each
2176 * notification type follow:
2178 * fdintCABINET_INFO:
2180 * This is the first notification provided after calling FDICopy, and provides
2181 * the user with various information about the cabinet. Note that this is
2182 * called for each cabinet FDICopy opens, not just the first one. In the
2183 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2184 * next cabinet file in the set after the one just loaded (if any), psz2
2185 * contains a pointer to the name or "info" of the next disk, psz3
2186 * contains a pointer to the file-path of the current cabinet, setID
2187 * contains an arbitrary constant associated with this set of cabinet files,
2188 * and iCabinet contains the numerical index of the current cabinet within
2189 * that set. Return zero, or -1 to abort.
2191 * fdintPARTIAL_FILE:
2193 * This notification is provided when FDICopy encounters a part of a file
2194 * contained in this cabinet which is missing its beginning. Files can be
2195 * split across cabinets, so this is not necessarily an abnormality; it just
2196 * means that the file in question begins in another cabinet. No file
2197 * corresponding to this notification is extracted from the cabinet. In the
2198 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2199 * partial file, psz2 contains a pointer to the file name of the cabinet in
2200 * which this file begins, and psz3 contains a pointer to the disk name or
2201 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2203 * fdintCOPY_FILE:
2205 * This notification is provided when FDICopy encounters a file which starts
2206 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2207 * look for files in cabinets after the first one). One notification will be
2208 * sent for each such file, before the file is decompressed. By returning
2209 * zero, the callback can instruct FDICopy to skip the file. In the structure
2210 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2211 * the size of the file (uncompressed), attribs contains the file attributes,
2212 * and date and time contain the date and time of the file. attributes, date,
2213 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2214 * for the entire cabinet, 0 to skip just this file but continue scanning the
2215 * cabinet for more files, or an FDIClose()-compatible file-handle.
2217 * fdintCLOSE_FILE_INFO:
2219 * This notification is important, don't forget to implement it. This
2220 * notification indicates that a file has been successfully uncompressed and
2221 * written to disk. Upon receipt of this notification, the callee is expected
2222 * to close the file handle, to set the attributes and date/time of the
2223 * closed file, and possibly to execute the file. In the structure pointed to
2224 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2225 * open file handle (close it), cb contains 1 or zero, indicating respectively
2226 * that the callee should or should not execute the file, and date, time
2227 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2228 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2229 * do so. Return TRUE, or FALSE to abort decompression.
2231 * fdintNEXT_CABINET:
2233 * This notification is called when FDICopy must load in another cabinet. This
2234 * can occur when a file's data is "split" across multiple cabinets. The
2235 * callee has the opportunity to request that FDICopy look in a different file
2236 * path for the specified cabinet file, by writing that data into a provided
2237 * buffer (see below for more information). This notification will be received
2238 * more than once per-cabinet in the instance that FDICopy failed to find a
2239 * valid cabinet at the location specified by the first per-cabinet
2240 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2241 * structure pointed to by pfdin indicates the error which prevented FDICopy
2242 * from proceeding successfully. Return zero to indicate success, or -1 to
2243 * indicate failure and abort FDICopy.
2245 * Upon receipt of this notification, the structure pointed to by pfdin will
2246 * contain the following values: psz1 pointing to the name of the cabinet
2247 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2248 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2249 * and fdie containing either FDIERROR_NONE, or one of the following:
2251 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2252 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2253 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2254 * FDIERROR_WRONG_CABINET.
2256 * The callee may choose to change the path where FDICopy will look for the
2257 * cabinet after this notification. To do so, the caller may write the new
2258 * pathname to the buffer pointed to by psz3, which is 256 characters in
2259 * length, including the terminating null character, before returning zero.
2261 * fdintENUMERATE:
2263 * Undocumented and unimplemented in wine, this seems to be sent each time
2264 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2265 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2266 * provides information about the current cabinet instead of the next one....
2267 * this is just a guess, it has not been looked at closely.
2269 * INCLUDES
2270 * fdi.c
2272 BOOL __cdecl FDICopy(
2273 HFDI hfdi,
2274 char *pszCabinet,
2275 char *pszCabPath,
2276 int flags,
2277 PFNFDINOTIFY pfnfdin,
2278 PFNFDIDECRYPT pfnfdid,
2279 void *pvUser)
2281 FDICABINETINFO fdici;
2282 FDINOTIFICATION fdin;
2283 int cabhf, filehf, idx;
2284 unsigned int i;
2285 char fullpath[MAX_PATH];
2286 size_t pathlen, filenamelen;
2287 char emptystring = '\0';
2288 cab_UBYTE buf[64];
2289 struct fdi_folder *fol = NULL, *linkfol = NULL;
2290 struct fdi_file *file = NULL, *linkfile = NULL;
2291 fdi_decomp_state _decomp_state;
2292 fdi_decomp_state *decomp_state = &_decomp_state;
2294 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, \
2295 pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2296 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2298 if (!REALLY_IS_FDI(hfdi)) {
2299 SetLastError(ERROR_INVALID_HANDLE);
2300 return FALSE;
2303 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2305 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2306 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2308 /* slight overestimation here to save CPU cycles in the developer's brain */
2309 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2310 ERR("MAX_PATH exceeded.\n");
2311 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2312 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2313 PFDI_INT(hfdi)->perf->fError = TRUE;
2314 SetLastError(ERROR_FILE_NOT_FOUND);
2315 return FALSE;
2318 /* paste the path and filename together */
2319 idx = 0;
2320 if (pathlen) {
2321 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2322 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2324 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2325 fullpath[idx] = '\0';
2327 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2329 /* get a handle to the cabfile */
2330 cabhf = PFDI_OPEN(hfdi, fullpath, 32768, _S_IREAD | _S_IWRITE);
2331 if (cabhf == -1) {
2332 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2333 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2334 PFDI_INT(hfdi)->perf->fError = TRUE;
2335 SetLastError(ERROR_FILE_NOT_FOUND);
2336 return FALSE;
2339 if (cabhf == 0) {
2340 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2341 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2342 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2343 PFDI_INT(hfdi)->perf->fError = TRUE;
2344 SetLastError(ERROR_FILE_NOT_FOUND);
2345 return FALSE;
2348 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2349 if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2350 ERR("FDIIsCabinet failed.\n");
2351 PFDI_CLOSE(hfdi, cabhf);
2352 return FALSE;
2355 /* cabinet notification */
2356 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2357 fdin.setID = fdici.setID;
2358 fdin.iCabinet = fdici.iCabinet;
2359 fdin.pv = pvUser;
2360 fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2361 fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2362 fdin.psz3 = pszCabPath;
2364 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2365 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2366 PFDI_INT(hfdi)->perf->erfType = 0;
2367 PFDI_INT(hfdi)->perf->fError = TRUE;
2368 goto bail_and_fail;
2371 CAB(setID) = fdici.setID;
2372 CAB(iCabinet) = fdici.iCabinet;
2374 /* read folders */
2375 for (i = 0; i < fdici.cFolders; i++) {
2376 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2377 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2378 PFDI_INT(hfdi)->perf->erfType = 0;
2379 PFDI_INT(hfdi)->perf->fError = TRUE;
2380 goto bail_and_fail;
2383 if (CAB(mii).folder_resv > 0)
2384 PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2386 fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2387 if (!fol) {
2388 ERR("out of memory!\n");
2389 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2390 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2391 PFDI_INT(hfdi)->perf->fError = TRUE;
2392 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2393 goto bail_and_fail;
2395 ZeroMemory(fol, sizeof(struct fdi_folder));
2396 if (!CAB(firstfol)) CAB(firstfol) = fol;
2398 fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2399 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2400 fol->comp_type = EndGetI16(buf+cffold_CompType);
2402 if (linkfol)
2403 linkfol->next = fol;
2404 linkfol = fol;
2407 /* read files */
2408 for (i = 0; i < fdici.cFiles; i++) {
2409 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2410 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2411 PFDI_INT(hfdi)->perf->erfType = 0;
2412 PFDI_INT(hfdi)->perf->fError = TRUE;
2413 goto bail_and_fail;
2416 file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2417 if (!file) {
2418 ERR("out of memory!\n");
2419 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2420 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2421 PFDI_INT(hfdi)->perf->fError = TRUE;
2422 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2423 goto bail_and_fail;
2425 ZeroMemory(file, sizeof(struct fdi_file));
2426 if (!CAB(firstfile)) CAB(firstfile) = file;
2428 file->length = EndGetI32(buf+cffile_UncompressedSize);
2429 file->offset = EndGetI32(buf+cffile_FolderOffset);
2430 file->index = EndGetI16(buf+cffile_FolderIndex);
2431 file->time = EndGetI16(buf+cffile_Time);
2432 file->date = EndGetI16(buf+cffile_Date);
2433 file->attribs = EndGetI16(buf+cffile_Attribs);
2434 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2436 if (!file->filename) {
2437 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2438 PFDI_INT(hfdi)->perf->erfType = 0;
2439 PFDI_INT(hfdi)->perf->fError = TRUE;
2440 goto bail_and_fail;
2443 if (linkfile)
2444 linkfile->next = file;
2445 linkfile = file;
2448 for (file = CAB(firstfile); (file); file = file->next) {
2451 * FIXME: This implementation keeps multiple cabinet files open at once
2452 * when encountering a split cabinet. It is a quirk of this implementation
2453 * that sometimes we decrypt the same block of data more than once, to find
2454 * the right starting point for a file, moving the file-pointer backwards.
2455 * If we kept a cache of certain file-pointer information, we could eliminate
2456 * that behavior... in fact I am not sure that the caching we already have
2457 * is not sufficient.
2459 * The current implementation seems to work fine in straightforward situations
2460 * where all the cabinet files needed for decryption are simultaneously
2461 * available. But presumably, the API is supposed to support cabinets which
2462 * are split across multiple CDROMS; we may need to change our implementation
2463 * to strictly serialize it's file usage so that it opens only one cabinet
2464 * at a time. Some experimentation with Windows is needed to figure out the
2465 * precise semantics required. The relevant code is here and in fdi_decomp().
2468 /* partial-file notification */
2469 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2471 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2472 * and perform some tests to figure out the right behavior. The SDK says
2473 * FDICopy will notify the user of the filename and "disk name" (info) of
2474 * the cabinet where the spanning file /started/.
2476 * That would certainly be convenient for the API-user, who could abort,
2477 * everything (or parallelize, if that's allowed (it is in wine)), and call
2478 * FDICopy again with the provided filename, so as to avoid partial file
2479 * notification and successfully unpack. This task could be quite unpleasant
2480 * from wine's perspective: the information specifying the "start cabinet" for
2481 * a file is associated nowhere with the file header and is not to be found in
2482 * the cabinet header. We have only the index of the cabinet wherein the folder
2483 * begins, which contains the file. To find that cabinet, we must consider the
2484 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2485 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2486 * list).
2488 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2489 * cabinet other than the active one might be at another filepath than the
2490 * current one, or on another CDROM. This could get rather dicey, especially
2491 * if we imagine parallelized access to the FDICopy API.
2493 * The current implementation punts -- it just returns the previous cabinet and
2494 * it's info from the header of this cabinet. This provides the right answer in
2495 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2496 * we "fix" it.
2498 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2499 fdin.pv = pvUser;
2500 fdin.psz1 = (char *)file->filename;
2501 fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2502 fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2504 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2505 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2506 PFDI_INT(hfdi)->perf->erfType = 0;
2507 PFDI_INT(hfdi)->perf->fError = TRUE;
2508 goto bail_and_fail;
2510 /* I don't think we are supposed to decompress partial files. This prevents it. */
2511 file->oppressed = TRUE;
2513 if (file->oppressed) {
2514 filehf = 0;
2515 } else {
2516 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2517 fdin.pv = pvUser;
2518 fdin.psz1 = (char *)file->filename;
2519 fdin.cb = file->length;
2520 fdin.date = file->date;
2521 fdin.time = file->time;
2522 fdin.attribs = file->attribs;
2523 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2524 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2525 PFDI_INT(hfdi)->perf->erfType = 0;
2526 PFDI_INT(hfdi)->perf->fError = TRUE;
2527 goto bail_and_fail;
2531 /* find the folder for this file if necc. */
2532 if (filehf) {
2533 int i2;
2535 fol = CAB(firstfol);
2536 if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2537 /* pick the last folder */
2538 while (fol->next) fol = fol->next;
2539 } else {
2540 for (i2 = 0; (i2 < file->index); i2++)
2541 if (fol->next) /* bug resistance, should always be true */
2542 fol = fol->next;
2546 if (filehf) {
2547 cab_UWORD comptype = fol->comp_type;
2548 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2549 int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2550 int err = 0;
2552 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2554 /* set up decomp_state */
2555 CAB(hfdi) = hfdi;
2556 CAB(filehf) = filehf;
2557 CAB(cabhf) = cabhf;
2559 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2560 if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2562 TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2564 /* free stuff for the old decompresser */
2565 switch (ct2) {
2566 case cffoldCOMPTYPE_LZX:
2567 if (LZX(window)) {
2568 PFDI_FREE(hfdi, LZX(window));
2569 LZX(window) = NULL;
2571 break;
2572 case cffoldCOMPTYPE_QUANTUM:
2573 if (QTM(window)) {
2574 PFDI_FREE(hfdi, QTM(window));
2575 QTM(window) = NULL;
2577 break;
2580 CAB(decomp_cab) = NULL;
2581 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2582 CAB(offset) = 0;
2583 CAB(outlen) = 0;
2585 /* initialize the new decompresser */
2586 switch (ct1) {
2587 case cffoldCOMPTYPE_NONE:
2588 CAB(decompress) = NONEfdi_decomp;
2589 break;
2590 case cffoldCOMPTYPE_MSZIP:
2591 CAB(decompress) = ZIPfdi_decomp;
2592 break;
2593 case cffoldCOMPTYPE_QUANTUM:
2594 CAB(decompress) = QTMfdi_decomp;
2595 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2596 break;
2597 case cffoldCOMPTYPE_LZX:
2598 CAB(decompress) = LZXfdi_decomp;
2599 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2600 break;
2601 default:
2602 err = DECR_DATAFORMAT;
2606 CAB(current) = fol;
2608 switch (err) {
2609 case DECR_OK:
2610 break;
2611 case DECR_NOMEMORY:
2612 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2613 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2614 PFDI_INT(hfdi)->perf->fError = TRUE;
2615 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2616 goto bail_and_fail;
2617 default:
2618 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2619 PFDI_INT(hfdi)->perf->erfOper = 0;
2620 PFDI_INT(hfdi)->perf->fError = TRUE;
2621 goto bail_and_fail;
2624 if (file->offset > CAB(offset)) {
2625 /* decode bytes and send them to /dev/null */
2626 switch ((err = fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser))) {
2627 case DECR_OK:
2628 break;
2629 case DECR_USERABORT:
2630 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2631 PFDI_INT(hfdi)->perf->erfType = 0;
2632 PFDI_INT(hfdi)->perf->fError = TRUE;
2633 goto bail_and_fail;
2634 case DECR_NOMEMORY:
2635 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2636 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2637 PFDI_INT(hfdi)->perf->fError = TRUE;
2638 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2639 goto bail_and_fail;
2640 default:
2641 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2642 PFDI_INT(hfdi)->perf->erfOper = 0;
2643 PFDI_INT(hfdi)->perf->fError = TRUE;
2644 goto bail_and_fail;
2646 CAB(offset) = file->offset;
2649 /* now do the actual decompression */
2650 err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2651 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2653 switch (err) {
2654 case DECR_OK:
2655 break;
2656 case DECR_USERABORT:
2657 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2658 PFDI_INT(hfdi)->perf->erfType = 0;
2659 PFDI_INT(hfdi)->perf->fError = TRUE;
2660 goto bail_and_fail;
2661 case DECR_NOMEMORY:
2662 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2663 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2664 PFDI_INT(hfdi)->perf->fError = TRUE;
2665 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2666 goto bail_and_fail;
2667 default:
2668 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2669 PFDI_INT(hfdi)->perf->erfOper = 0;
2670 PFDI_INT(hfdi)->perf->fError = TRUE;
2671 goto bail_and_fail;
2674 /* fdintCLOSE_FILE_INFO notification */
2675 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2676 fdin.pv = pvUser;
2677 fdin.psz1 = (char *)file->filename;
2678 fdin.hf = filehf;
2679 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2680 fdin.date = file->date;
2681 fdin.time = file->time;
2682 fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2683 err = ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2684 if (err == FALSE || err == -1) {
2686 * SDK states that even though they indicated failure,
2687 * we are not supposed to try and close the file, so we
2688 * just treat this like all the others
2690 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2691 PFDI_INT(hfdi)->perf->erfType = 0;
2692 PFDI_INT(hfdi)->perf->fError = TRUE;
2693 goto bail_and_fail;
2698 /* free decompression temps */
2699 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2700 case cffoldCOMPTYPE_LZX:
2701 if (LZX(window)) {
2702 PFDI_FREE(hfdi, LZX(window));
2703 LZX(window) = NULL;
2705 break;
2706 case cffoldCOMPTYPE_QUANTUM:
2707 if (QTM(window)) {
2708 PFDI_FREE(hfdi, QTM(window));
2709 QTM(window) = NULL;
2711 break;
2714 while (decomp_state) {
2715 fdi_decomp_state *prev_fds;
2717 PFDI_CLOSE(hfdi, CAB(cabhf));
2719 /* free the storage remembered by mii */
2720 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2721 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2722 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2723 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2725 while (CAB(firstfol)) {
2726 fol = CAB(firstfol);
2727 CAB(firstfol) = CAB(firstfol)->next;
2728 PFDI_FREE(hfdi, fol);
2730 while (CAB(firstfile)) {
2731 file = CAB(firstfile);
2732 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2733 CAB(firstfile) = CAB(firstfile)->next;
2734 PFDI_FREE(hfdi, file);
2736 prev_fds = decomp_state;
2737 decomp_state = CAB(next);
2738 if (prev_fds != &_decomp_state)
2739 PFDI_FREE(hfdi, prev_fds);
2742 return TRUE;
2744 bail_and_fail: /* here we free ram before error returns */
2746 /* free decompression temps */
2747 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2748 case cffoldCOMPTYPE_LZX:
2749 if (LZX(window)) {
2750 PFDI_FREE(hfdi, LZX(window));
2751 LZX(window) = NULL;
2753 break;
2754 case cffoldCOMPTYPE_QUANTUM:
2755 if (QTM(window)) {
2756 PFDI_FREE(hfdi, QTM(window));
2757 QTM(window) = NULL;
2759 break;
2762 while (decomp_state) {
2763 fdi_decomp_state *prev_fds;
2765 PFDI_CLOSE(hfdi, CAB(cabhf));
2767 /* free the storage remembered by mii */
2768 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2769 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2770 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2771 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2773 while (CAB(firstfol)) {
2774 fol = CAB(firstfol);
2775 CAB(firstfol) = CAB(firstfol)->next;
2776 PFDI_FREE(hfdi, fol);
2778 while (CAB(firstfile)) {
2779 file = CAB(firstfile);
2780 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2781 CAB(firstfile) = CAB(firstfile)->next;
2782 PFDI_FREE(hfdi, file);
2784 prev_fds = decomp_state;
2785 decomp_state = CAB(next);
2786 if (prev_fds != &_decomp_state)
2787 PFDI_FREE(hfdi, prev_fds);
2790 return FALSE;
2793 /***********************************************************************
2794 * FDIDestroy (CABINET.23)
2796 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2797 * of FDICopy. Only reason for failure would be an invalid handle.
2799 * PARAMS
2800 * hfdi [I] The HFDI to free
2802 * RETURNS
2803 * TRUE for success
2804 * FALSE for failure
2806 BOOL __cdecl FDIDestroy(HFDI hfdi)
2808 TRACE("(hfdi == ^%p)\n", hfdi);
2809 if (REALLY_IS_FDI(hfdi)) {
2810 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2811 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2812 return TRUE;
2813 } else {
2814 SetLastError(ERROR_INVALID_HANDLE);
2815 return FALSE;
2819 /***********************************************************************
2820 * FDITruncateCabinet (CABINET.24)
2822 * Undocumented and unimplemented.
2824 BOOL __cdecl FDITruncateCabinet(
2825 HFDI hfdi,
2826 char *pszCabinetName,
2827 USHORT iFolderToDelete)
2829 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2830 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2832 if (!REALLY_IS_FDI(hfdi)) {
2833 SetLastError(ERROR_INVALID_HANDLE);
2834 return FALSE;
2837 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2838 return FALSE;