Added missing comma in index.html.
[wine.git] / dlls / cabinet / fdi.c
blob9a1f9b7e3308910e5030b70a0270d5bcd9df52b9
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 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 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 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 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 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 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 int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
653 int wndsize = 1 << window, msz = window * 2, i;
654 cab_ULONG j;
656 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
657 /* if a previously allocated window is big enough, keep it */
658 if (window < 10 || window > 21) return DECR_DATAFORMAT;
659 if (QTM(actual_size) < wndsize) {
660 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
661 QTM(window) = NULL;
663 if (!QTM(window)) {
664 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
665 QTM(actual_size) = wndsize;
667 QTM(window_size) = wndsize;
668 QTM(window_posn) = 0;
670 /* initialize static slot/extrabits tables */
671 for (i = 0, j = 0; i < 27; i++) {
672 CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
673 CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
675 for (i = 0, j = 0; i < 42; i++) {
676 CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
677 CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
680 /* initialize arithmetic coding models */
682 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
684 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
685 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
686 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
687 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
689 /* model 4 depends on table size, ranges from 20 to 24 */
690 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
691 /* model 5 depends on table size, ranges from 20 to 36 */
692 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
693 /* model 6pos depends on table size, ranges from 20 to 42 */
694 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
695 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
697 return DECR_OK;
700 /************************************************************
701 * LZXfdi_init (internal)
703 int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
704 cab_ULONG wndsize = 1 << window;
705 int i, j, posn_slots;
707 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
708 /* if a previously allocated window is big enough, keep it */
709 if (window < 15 || window > 21) return DECR_DATAFORMAT;
710 if (LZX(actual_size) < wndsize) {
711 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
712 LZX(window) = NULL;
714 if (!LZX(window)) {
715 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
716 LZX(actual_size) = wndsize;
718 LZX(window_size) = wndsize;
720 /* initialize static tables */
721 for (i=0, j=0; i <= 50; i += 2) {
722 CAB(extra_bits)[i] = CAB(extra_bits)[i+1] = j; /* 0,0,0,0,1,1,2,2,3,3... */
723 if ((i != 0) && (j < 17)) j++; /* 0,0,1,2,3,4...15,16,17,17,17,17... */
725 for (i=0, j=0; i <= 50; i++) {
726 CAB(lzx_position_base)[i] = j; /* 0,1,2,3,4,6,8,12,16,24,32,... */
727 j += 1 << CAB(extra_bits)[i]; /* 1,1,1,1,2,2,4,4,8,8,16,16,32,32,... */
730 /* calculate required position slots */
731 if (window == 20) posn_slots = 42;
732 else if (window == 21) posn_slots = 50;
733 else posn_slots = window << 1;
735 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
737 LZX(R0) = LZX(R1) = LZX(R2) = 1;
738 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
739 LZX(header_read) = 0;
740 LZX(frames_read) = 0;
741 LZX(block_remaining) = 0;
742 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
743 LZX(intel_curpos) = 0;
744 LZX(intel_started) = 0;
745 LZX(window_posn) = 0;
747 /* initialize tables to 0 (because deltas will be applied to them) */
748 for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) LZX(MAINTREE_len)[i] = 0;
749 for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) LZX(LENGTH_len)[i] = 0;
751 return DECR_OK;
754 /****************************************************
755 * NONEfdi_decomp(internal)
757 int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
759 if (inlen != outlen) return DECR_ILLEGALDATA;
760 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
761 return DECR_OK;
764 /********************************************************
765 * Ziphuft_free (internal)
767 void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
769 register struct Ziphuft *p, *q;
771 /* Go through linked list, freeing from the allocated (t[-1]) address. */
772 p = t;
773 while (p != (struct Ziphuft *)NULL)
775 q = (--p)->v.t;
776 PFDI_FREE(hfdi, p);
777 p = q;
781 /*********************************************************
782 * fdi_Ziphuft_build (internal)
784 cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, cab_UWORD *d, cab_UWORD *e,
785 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
787 cab_ULONG a; /* counter for codes of length k */
788 cab_ULONG el; /* length of EOB code (value 256) */
789 cab_ULONG f; /* i repeats in table every f entries */
790 cab_LONG g; /* maximum code length */
791 cab_LONG h; /* table level */
792 register cab_ULONG i; /* counter, current code */
793 register cab_ULONG j; /* counter */
794 register cab_LONG k; /* number of bits in current code */
795 cab_LONG *l; /* stack of bits per table */
796 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
797 register struct Ziphuft *q; /* points to current table */
798 struct Ziphuft r; /* table entry for structure assignment */
799 register cab_LONG w; /* bits before this table == (l * h) */
800 cab_ULONG *xp; /* pointer into x */
801 cab_LONG y; /* number of dummy codes added */
802 cab_ULONG z; /* number of entries in current table */
804 l = ZIP(lx)+1;
806 /* Generate counts for each bit length */
807 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
809 for(i = 0; i < ZIPBMAX+1; ++i)
810 ZIP(c)[i] = 0;
811 p = b; i = n;
814 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
815 } while (--i);
816 if (ZIP(c)[0] == n) /* null input--all zero length codes */
818 *t = (struct Ziphuft *)NULL;
819 *m = 0;
820 return 0;
823 /* Find minimum and maximum length, bound *m by those */
824 for (j = 1; j <= ZIPBMAX; j++)
825 if (ZIP(c)[j])
826 break;
827 k = j; /* minimum code length */
828 if ((cab_ULONG)*m < j)
829 *m = j;
830 for (i = ZIPBMAX; i; i--)
831 if (ZIP(c)[i])
832 break;
833 g = i; /* maximum code length */
834 if ((cab_ULONG)*m > i)
835 *m = i;
837 /* Adjust last length count to fill out codes, if needed */
838 for (y = 1 << j; j < i; j++, y <<= 1)
839 if ((y -= ZIP(c)[j]) < 0)
840 return 2; /* bad input: more codes than bits */
841 if ((y -= ZIP(c)[i]) < 0)
842 return 2;
843 ZIP(c)[i] += y;
845 /* Generate starting offsets LONGo the value table for each length */
846 ZIP(x)[1] = j = 0;
847 p = ZIP(c) + 1; xp = ZIP(x) + 2;
848 while (--i)
849 { /* note that i == g from above */
850 *xp++ = (j += *p++);
853 /* Make a table of values in order of bit lengths */
854 p = b; i = 0;
856 if ((j = *p++) != 0)
857 ZIP(v)[ZIP(x)[j]++] = i;
858 } while (++i < n);
861 /* Generate the Huffman codes and for each, make the table entries */
862 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
863 p = ZIP(v); /* grab values in bit order */
864 h = -1; /* no tables yet--level -1 */
865 w = l[-1] = 0; /* no bits decoded yet */
866 ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */
867 q = (struct Ziphuft *)NULL; /* ditto */
868 z = 0; /* ditto */
870 /* go through the bit lengths (k already is bits in shortest code) */
871 for (; k <= g; k++)
873 a = ZIP(c)[k];
874 while (a--)
876 /* here i is the Huffman code of length k bits for value *p */
877 /* make tables up to required level */
878 while (k > w + l[h])
880 w += l[h++]; /* add bits already decoded */
882 /* compute minimum size table less than or equal to *m bits */
883 z = (z = g - w) > (cab_ULONG)*m ? *m : z; /* upper limit */
884 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
885 { /* too few codes for k-w bit table */
886 f -= a + 1; /* deduct codes from patterns left */
887 xp = ZIP(c) + k;
888 while (++j < z) /* try smaller tables up to z bits */
890 if ((f <<= 1) <= *++xp)
891 break; /* enough codes to use up j bits */
892 f -= *xp; /* else deduct codes from patterns */
895 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
896 j = el - w; /* make EOB code end at table */
897 z = 1 << j; /* table entries for j-bit table */
898 l[h] = j; /* set table size in stack */
900 /* allocate and link in new table */
901 if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
903 if(h)
904 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
905 return 3; /* not enough memory */
907 *t = q + 1; /* link to list for Ziphuft_free() */
908 *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
909 ZIP(u)[h] = ++q; /* table starts after link */
911 /* connect to last table, if there is one */
912 if (h)
914 ZIP(x)[h] = i; /* save pattern for backing up */
915 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
916 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
917 r.v.t = q; /* pointer to this table */
918 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
919 ZIP(u)[h-1][j] = r; /* connect to last table */
923 /* set up table entry in r */
924 r.b = (cab_UBYTE)(k - w);
925 if (p >= ZIP(v) + n)
926 r.e = 99; /* out of values--invalid code */
927 else if (*p < s)
929 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
930 r.v.n = *p++; /* simple code is just the value */
932 else
934 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
935 r.v.n = d[*p++ - s];
938 /* fill code-like entries with r */
939 f = 1 << (k - w);
940 for (j = i >> w; j < z; j += f)
941 q[j] = r;
943 /* backwards increment the k-bit code i */
944 for (j = 1 << (k - 1); i & j; j >>= 1)
945 i ^= j;
946 i ^= j;
948 /* backup over finished tables */
949 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
950 w -= l[--h]; /* don't need to update q */
954 /* return actual size of base table */
955 *m = l[0];
957 /* Return true (1) if we were given an incomplete table */
958 return y != 0 && g != 1;
961 /*********************************************************
962 * fdi_Zipinflate_codes (internal)
964 cab_LONG fdi_Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td,
965 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
967 register cab_ULONG e; /* table entry flag/number of extra bits */
968 cab_ULONG n, d; /* length and index for copy */
969 cab_ULONG w; /* current window position */
970 struct Ziphuft *t; /* pointer to table entry */
971 cab_ULONG ml, md; /* masks for bl and bd bits */
972 register cab_ULONG b; /* bit buffer */
973 register cab_ULONG k; /* number of bits in bit buffer */
975 /* make local copies of globals */
976 b = ZIP(bb); /* initialize bit buffer */
977 k = ZIP(bk);
978 w = ZIP(window_posn); /* initialize window position */
980 /* inflate the coded data */
981 ml = Zipmask[bl]; /* precompute masks for speed */
982 md = Zipmask[bd];
984 for(;;)
986 ZIPNEEDBITS((cab_ULONG)bl)
987 if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16)
990 if (e == 99)
991 return 1;
992 ZIPDUMPBITS(t->b)
993 e -= 16;
994 ZIPNEEDBITS(e)
995 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
996 ZIPDUMPBITS(t->b)
997 if (e == 16) /* then it's a literal */
998 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
999 else /* it's an EOB or a length */
1001 /* exit if end of block */
1002 if(e == 15)
1003 break;
1005 /* get length of block to copy */
1006 ZIPNEEDBITS(e)
1007 n = t->v.n + ((cab_ULONG)b & Zipmask[e]);
1008 ZIPDUMPBITS(e);
1010 /* decode distance of block to copy */
1011 ZIPNEEDBITS((cab_ULONG)bd)
1012 if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16)
1013 do {
1014 if (e == 99)
1015 return 1;
1016 ZIPDUMPBITS(t->b)
1017 e -= 16;
1018 ZIPNEEDBITS(e)
1019 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
1020 ZIPDUMPBITS(t->b)
1021 ZIPNEEDBITS(e)
1022 d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]);
1023 ZIPDUMPBITS(e)
1026 n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
1029 CAB(outbuf)[w++] = CAB(outbuf)[d++];
1030 } while (--e);
1031 } while (n);
1035 /* restore the globals from the locals */
1036 ZIP(window_posn) = w; /* restore global window pointer */
1037 ZIP(bb) = b; /* restore global bit buffer */
1038 ZIP(bk) = k;
1040 /* done */
1041 return 0;
1044 /***********************************************************
1045 * Zipinflate_stored (internal)
1047 cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1048 /* "decompress" an inflated type 0 (stored) block. */
1050 cab_ULONG n; /* number of bytes in block */
1051 cab_ULONG w; /* current window position */
1052 register cab_ULONG b; /* bit buffer */
1053 register cab_ULONG k; /* number of bits in bit buffer */
1055 /* make local copies of globals */
1056 b = ZIP(bb); /* initialize bit buffer */
1057 k = ZIP(bk);
1058 w = ZIP(window_posn); /* initialize window position */
1060 /* go to byte boundary */
1061 n = k & 7;
1062 ZIPDUMPBITS(n);
1064 /* get the length and its complement */
1065 ZIPNEEDBITS(16)
1066 n = ((cab_ULONG)b & 0xffff);
1067 ZIPDUMPBITS(16)
1068 ZIPNEEDBITS(16)
1069 if (n != (cab_ULONG)((~b) & 0xffff))
1070 return 1; /* error in compressed data */
1071 ZIPDUMPBITS(16)
1073 /* read and output the compressed data */
1074 while(n--)
1076 ZIPNEEDBITS(8)
1077 CAB(outbuf)[w++] = (cab_UBYTE)b;
1078 ZIPDUMPBITS(8)
1081 /* restore the globals from the locals */
1082 ZIP(window_posn) = w; /* restore global window pointer */
1083 ZIP(bb) = b; /* restore global bit buffer */
1084 ZIP(bk) = k;
1085 return 0;
1088 /******************************************************
1089 * fdi_Zipinflate_fixed (internal)
1091 cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1093 struct Ziphuft *fixed_tl;
1094 struct Ziphuft *fixed_td;
1095 cab_LONG fixed_bl, fixed_bd;
1096 cab_LONG i; /* temporary variable */
1097 cab_ULONG *l;
1099 l = ZIP(ll);
1101 /* literal table */
1102 for(i = 0; i < 144; i++)
1103 l[i] = 8;
1104 for(; i < 256; i++)
1105 l[i] = 9;
1106 for(; i < 280; i++)
1107 l[i] = 7;
1108 for(; i < 288; i++) /* make a complete, but wrong code set */
1109 l[i] = 8;
1110 fixed_bl = 7;
1111 if((i = fdi_Ziphuft_build(l, 288, 257, (cab_UWORD *) Zipcplens,
1112 (cab_UWORD *) Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1113 return i;
1115 /* distance table */
1116 for(i = 0; i < 30; i++) /* make an incomplete code set */
1117 l[i] = 5;
1118 fixed_bd = 5;
1119 if((i = fdi_Ziphuft_build(l, 30, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
1120 &fixed_td, &fixed_bd, decomp_state)) > 1)
1122 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1123 return i;
1126 /* decompress until an end-of-block code */
1127 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1129 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1130 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1131 return i;
1134 /**************************************************************
1135 * fdi_Zipinflate_dynamic (internal)
1137 cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1138 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1140 cab_LONG i; /* temporary variables */
1141 cab_ULONG j;
1142 cab_ULONG *ll;
1143 cab_ULONG l; /* last length */
1144 cab_ULONG m; /* mask for bit lengths table */
1145 cab_ULONG n; /* number of lengths to get */
1146 struct Ziphuft *tl; /* literal/length code table */
1147 struct Ziphuft *td; /* distance code table */
1148 cab_LONG bl; /* lookup bits for tl */
1149 cab_LONG bd; /* lookup bits for td */
1150 cab_ULONG nb; /* number of bit length codes */
1151 cab_ULONG nl; /* number of literal/length codes */
1152 cab_ULONG nd; /* number of distance codes */
1153 register cab_ULONG b; /* bit buffer */
1154 register cab_ULONG k; /* number of bits in bit buffer */
1156 /* make local bit buffer */
1157 b = ZIP(bb);
1158 k = ZIP(bk);
1159 ll = ZIP(ll);
1161 /* read in table lengths */
1162 ZIPNEEDBITS(5)
1163 nl = 257 + ((cab_ULONG)b & 0x1f); /* number of literal/length codes */
1164 ZIPDUMPBITS(5)
1165 ZIPNEEDBITS(5)
1166 nd = 1 + ((cab_ULONG)b & 0x1f); /* number of distance codes */
1167 ZIPDUMPBITS(5)
1168 ZIPNEEDBITS(4)
1169 nb = 4 + ((cab_ULONG)b & 0xf); /* number of bit length codes */
1170 ZIPDUMPBITS(4)
1171 if(nl > 288 || nd > 32)
1172 return 1; /* bad lengths */
1174 /* read in bit-length-code lengths */
1175 for(j = 0; j < nb; j++)
1177 ZIPNEEDBITS(3)
1178 ll[Zipborder[j]] = (cab_ULONG)b & 7;
1179 ZIPDUMPBITS(3)
1181 for(; j < 19; j++)
1182 ll[Zipborder[j]] = 0;
1184 /* build decoding table for trees--single level, 7 bit lookup */
1185 bl = 7;
1186 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1188 if(i == 1)
1189 fdi_Ziphuft_free(CAB(hfdi), tl);
1190 return i; /* incomplete code set */
1193 /* read in literal and distance code lengths */
1194 n = nl + nd;
1195 m = Zipmask[bl];
1196 i = l = 0;
1197 while((cab_ULONG)i < n)
1199 ZIPNEEDBITS((cab_ULONG)bl)
1200 j = (td = tl + ((cab_ULONG)b & m))->b;
1201 ZIPDUMPBITS(j)
1202 j = td->v.n;
1203 if (j < 16) /* length of code in bits (0..15) */
1204 ll[i++] = l = j; /* save last length in l */
1205 else if (j == 16) /* repeat last length 3 to 6 times */
1207 ZIPNEEDBITS(2)
1208 j = 3 + ((cab_ULONG)b & 3);
1209 ZIPDUMPBITS(2)
1210 if((cab_ULONG)i + j > n)
1211 return 1;
1212 while (j--)
1213 ll[i++] = l;
1215 else if (j == 17) /* 3 to 10 zero length codes */
1217 ZIPNEEDBITS(3)
1218 j = 3 + ((cab_ULONG)b & 7);
1219 ZIPDUMPBITS(3)
1220 if ((cab_ULONG)i + j > n)
1221 return 1;
1222 while (j--)
1223 ll[i++] = 0;
1224 l = 0;
1226 else /* j == 18: 11 to 138 zero length codes */
1228 ZIPNEEDBITS(7)
1229 j = 11 + ((cab_ULONG)b & 0x7f);
1230 ZIPDUMPBITS(7)
1231 if ((cab_ULONG)i + j > n)
1232 return 1;
1233 while (j--)
1234 ll[i++] = 0;
1235 l = 0;
1239 /* free decoding table for trees */
1240 fdi_Ziphuft_free(CAB(hfdi), tl);
1242 /* restore the global bit buffer */
1243 ZIP(bb) = b;
1244 ZIP(bk) = k;
1246 /* build the decoding tables for literal/length and distance codes */
1247 bl = ZIPLBITS;
1248 if((i = fdi_Ziphuft_build(ll, nl, 257, (cab_UWORD *) Zipcplens, (cab_UWORD *) Zipcplext,
1249 &tl, &bl, decomp_state)) != 0)
1251 if(i == 1)
1252 fdi_Ziphuft_free(CAB(hfdi), tl);
1253 return i; /* incomplete code set */
1255 bd = ZIPDBITS;
1256 fdi_Ziphuft_build(ll + nl, nd, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
1257 &td, &bd, decomp_state);
1259 /* decompress until an end-of-block code */
1260 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1261 return 1;
1263 /* free the decoding tables, return */
1264 fdi_Ziphuft_free(CAB(hfdi), tl);
1265 fdi_Ziphuft_free(CAB(hfdi), td);
1266 return 0;
1269 /*****************************************************
1270 * fdi_Zipinflate_block (internal)
1272 cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1273 { /* decompress an inflated block */
1274 cab_ULONG t; /* block type */
1275 register cab_ULONG b; /* bit buffer */
1276 register cab_ULONG k; /* number of bits in bit buffer */
1278 /* make local bit buffer */
1279 b = ZIP(bb);
1280 k = ZIP(bk);
1282 /* read in last block bit */
1283 ZIPNEEDBITS(1)
1284 *e = (cab_LONG)b & 1;
1285 ZIPDUMPBITS(1)
1287 /* read in block type */
1288 ZIPNEEDBITS(2)
1289 t = (cab_ULONG)b & 3;
1290 ZIPDUMPBITS(2)
1292 /* restore the global bit buffer */
1293 ZIP(bb) = b;
1294 ZIP(bk) = k;
1296 /* inflate that block type */
1297 if(t == 2)
1298 return fdi_Zipinflate_dynamic(decomp_state);
1299 if(t == 0)
1300 return fdi_Zipinflate_stored(decomp_state);
1301 if(t == 1)
1302 return fdi_Zipinflate_fixed(decomp_state);
1303 /* bad block type */
1304 return 2;
1307 /****************************************************
1308 * ZIPfdi_decomp(internal)
1310 int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1312 cab_LONG e; /* last block flag */
1314 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1316 ZIP(inpos) = CAB(inbuf);
1317 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1318 if(outlen > ZIPWSIZE)
1319 return DECR_DATAFORMAT;
1321 /* CK = Chris Kirmse, official Microsoft purloiner */
1322 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1323 return DECR_ILLEGALDATA;
1324 ZIP(inpos) += 2;
1326 do {
1327 if(fdi_Zipinflate_block(&e, decomp_state))
1328 return DECR_ILLEGALDATA;
1329 } while(!e);
1331 /* return success */
1332 return DECR_OK;
1335 /*******************************************************************
1336 * QTMfdi_decomp(internal)
1338 int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1340 cab_UBYTE *inpos = CAB(inbuf);
1341 cab_UBYTE *window = QTM(window);
1342 cab_UBYTE *runsrc, *rundest;
1344 cab_ULONG window_posn = QTM(window_posn);
1345 cab_ULONG window_size = QTM(window_size);
1347 /* used by bitstream macros */
1348 register int bitsleft, bitrun, bitsneed;
1349 register cab_ULONG bitbuf;
1351 /* used by GET_SYMBOL */
1352 cab_ULONG range;
1353 cab_UWORD symf;
1354 int i;
1356 int extra, togo = outlen, match_length = 0, copy_length;
1357 cab_UBYTE selector, sym;
1358 cab_ULONG match_offset = 0;
1360 cab_UWORD H = 0xFFFF, L = 0, C;
1362 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1364 /* read initial value of C */
1365 Q_INIT_BITSTREAM;
1366 Q_READ_BITS(C, 16);
1368 /* apply 2^x-1 mask */
1369 window_posn &= window_size - 1;
1370 /* runs can't straddle the window wraparound */
1371 if ((window_posn + togo) > window_size) {
1372 TRACE("straddled run\n");
1373 return DECR_DATAFORMAT;
1376 while (togo > 0) {
1377 GET_SYMBOL(model7, selector);
1378 switch (selector) {
1379 case 0:
1380 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1381 break;
1382 case 1:
1383 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1384 break;
1385 case 2:
1386 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1387 break;
1388 case 3:
1389 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1390 break;
1392 case 4:
1393 /* selector 4 = fixed length of 3 */
1394 GET_SYMBOL(model4, sym);
1395 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1396 match_offset = CAB(q_position_base)[sym] + extra + 1;
1397 match_length = 3;
1398 break;
1400 case 5:
1401 /* selector 5 = fixed length of 4 */
1402 GET_SYMBOL(model5, sym);
1403 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1404 match_offset = CAB(q_position_base)[sym] + extra + 1;
1405 match_length = 4;
1406 break;
1408 case 6:
1409 /* selector 6 = variable length */
1410 GET_SYMBOL(model6len, sym);
1411 Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1412 match_length = CAB(q_length_base)[sym] + extra + 5;
1413 GET_SYMBOL(model6pos, sym);
1414 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1415 match_offset = CAB(q_position_base)[sym] + extra + 1;
1416 break;
1418 default:
1419 TRACE("Selector is bogus\n");
1420 return DECR_ILLEGALDATA;
1423 /* if this is a match */
1424 if (selector >= 4) {
1425 rundest = window + window_posn;
1426 togo -= match_length;
1428 /* copy any wrapped around source data */
1429 if (window_posn >= match_offset) {
1430 /* no wrap */
1431 runsrc = rundest - match_offset;
1432 } else {
1433 runsrc = rundest + (window_size - match_offset);
1434 copy_length = match_offset - window_posn;
1435 if (copy_length < match_length) {
1436 match_length -= copy_length;
1437 window_posn += copy_length;
1438 while (copy_length-- > 0) *rundest++ = *runsrc++;
1439 runsrc = window;
1442 window_posn += match_length;
1444 /* copy match data - no worries about destination wraps */
1445 while (match_length-- > 0) *rundest++ = *runsrc++;
1447 } /* while (togo > 0) */
1449 if (togo != 0) {
1450 TRACE("Frame overflow, this_run = %d\n", togo);
1451 return DECR_ILLEGALDATA;
1454 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1455 outlen, outlen);
1457 QTM(window_posn) = window_posn;
1458 return DECR_OK;
1461 /************************************************************
1462 * fdi_lzx_read_lens (internal)
1464 int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1465 fdi_decomp_state *decomp_state) {
1466 cab_ULONG i,j, x,y;
1467 int z;
1469 register cab_ULONG bitbuf = lb->bb;
1470 register int bitsleft = lb->bl;
1471 cab_UBYTE *inpos = lb->ip;
1472 cab_UWORD *hufftbl;
1474 for (x = 0; x < 20; x++) {
1475 READ_BITS(y, 4);
1476 LENTABLE(PRETREE)[x] = y;
1478 BUILD_TABLE(PRETREE);
1480 for (x = first; x < last; ) {
1481 READ_HUFFSYM(PRETREE, z);
1482 if (z == 17) {
1483 READ_BITS(y, 4); y += 4;
1484 while (y--) lens[x++] = 0;
1486 else if (z == 18) {
1487 READ_BITS(y, 5); y += 20;
1488 while (y--) lens[x++] = 0;
1490 else if (z == 19) {
1491 READ_BITS(y, 1); y += 4;
1492 READ_HUFFSYM(PRETREE, z);
1493 z = lens[x] - z; if (z < 0) z += 17;
1494 while (y--) lens[x++] = z;
1496 else {
1497 z = lens[x] - z; if (z < 0) z += 17;
1498 lens[x++] = z;
1502 lb->bb = bitbuf;
1503 lb->bl = bitsleft;
1504 lb->ip = inpos;
1505 return 0;
1508 /*******************************************************
1509 * LZXfdi_decomp(internal)
1511 int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1512 cab_UBYTE *inpos = CAB(inbuf);
1513 cab_UBYTE *endinp = inpos + inlen;
1514 cab_UBYTE *window = LZX(window);
1515 cab_UBYTE *runsrc, *rundest;
1516 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1518 cab_ULONG window_posn = LZX(window_posn);
1519 cab_ULONG window_size = LZX(window_size);
1520 cab_ULONG R0 = LZX(R0);
1521 cab_ULONG R1 = LZX(R1);
1522 cab_ULONG R2 = LZX(R2);
1524 register cab_ULONG bitbuf;
1525 register int bitsleft;
1526 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1527 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1529 int togo = outlen, this_run, main_element, aligned_bits;
1530 int match_length, copy_length, length_footer, extra, verbatim_bits;
1532 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1534 INIT_BITSTREAM;
1536 /* read header if necessary */
1537 if (!LZX(header_read)) {
1538 i = j = 0;
1539 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1540 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1541 LZX(header_read) = 1;
1544 /* main decoding loop */
1545 while (togo > 0) {
1546 /* last block finished, new block expected */
1547 if (LZX(block_remaining) == 0) {
1548 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1549 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1550 INIT_BITSTREAM;
1553 READ_BITS(LZX(block_type), 3);
1554 READ_BITS(i, 16);
1555 READ_BITS(j, 8);
1556 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1558 switch (LZX(block_type)) {
1559 case LZX_BLOCKTYPE_ALIGNED:
1560 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1561 BUILD_TABLE(ALIGNED);
1562 /* rest of aligned header is same as verbatim */
1564 case LZX_BLOCKTYPE_VERBATIM:
1565 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1566 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1567 BUILD_TABLE(MAINTREE);
1568 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1570 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1571 BUILD_TABLE(LENGTH);
1572 break;
1574 case LZX_BLOCKTYPE_UNCOMPRESSED:
1575 LZX(intel_started) = 1; /* because we can't assume otherwise */
1576 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1577 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1578 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1579 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1580 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1581 break;
1583 default:
1584 return DECR_ILLEGALDATA;
1588 /* buffer exhaustion check */
1589 if (inpos > endinp) {
1590 /* it's possible to have a file where the next run is less than
1591 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1592 * in building the tables will exhaust the buffer, so we should
1593 * allow for this, but not allow those accidentally read bits to
1594 * be used (so we check that there are at least 16 bits
1595 * remaining - in this boundary case they aren't really part of
1596 * the compressed data)
1598 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1601 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1602 if (this_run > togo) this_run = togo;
1603 togo -= this_run;
1604 LZX(block_remaining) -= this_run;
1606 /* apply 2^x-1 mask */
1607 window_posn &= window_size - 1;
1608 /* runs can't straddle the window wraparound */
1609 if ((window_posn + this_run) > window_size)
1610 return DECR_DATAFORMAT;
1612 switch (LZX(block_type)) {
1614 case LZX_BLOCKTYPE_VERBATIM:
1615 while (this_run > 0) {
1616 READ_HUFFSYM(MAINTREE, main_element);
1618 if (main_element < LZX_NUM_CHARS) {
1619 /* literal: 0 to LZX_NUM_CHARS-1 */
1620 window[window_posn++] = main_element;
1621 this_run--;
1623 else {
1624 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1625 main_element -= LZX_NUM_CHARS;
1627 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1628 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1629 READ_HUFFSYM(LENGTH, length_footer);
1630 match_length += length_footer;
1632 match_length += LZX_MIN_MATCH;
1634 match_offset = main_element >> 3;
1636 if (match_offset > 2) {
1637 /* not repeated offset */
1638 if (match_offset != 3) {
1639 extra = CAB(extra_bits)[match_offset];
1640 READ_BITS(verbatim_bits, extra);
1641 match_offset = CAB(lzx_position_base)[match_offset]
1642 - 2 + verbatim_bits;
1644 else {
1645 match_offset = 1;
1648 /* update repeated offset LRU queue */
1649 R2 = R1; R1 = R0; R0 = match_offset;
1651 else if (match_offset == 0) {
1652 match_offset = R0;
1654 else if (match_offset == 1) {
1655 match_offset = R1;
1656 R1 = R0; R0 = match_offset;
1658 else /* match_offset == 2 */ {
1659 match_offset = R2;
1660 R2 = R0; R0 = match_offset;
1663 rundest = window + window_posn;
1664 this_run -= match_length;
1666 /* copy any wrapped around source data */
1667 if (window_posn >= match_offset) {
1668 /* no wrap */
1669 runsrc = rundest - match_offset;
1670 } else {
1671 runsrc = rundest + (window_size - match_offset);
1672 copy_length = match_offset - window_posn;
1673 if (copy_length < match_length) {
1674 match_length -= copy_length;
1675 window_posn += copy_length;
1676 while (copy_length-- > 0) *rundest++ = *runsrc++;
1677 runsrc = window;
1680 window_posn += match_length;
1682 /* copy match data - no worries about destination wraps */
1683 while (match_length-- > 0) *rundest++ = *runsrc++;
1686 break;
1688 case LZX_BLOCKTYPE_ALIGNED:
1689 while (this_run > 0) {
1690 READ_HUFFSYM(MAINTREE, main_element);
1692 if (main_element < LZX_NUM_CHARS) {
1693 /* literal: 0 to LZX_NUM_CHARS-1 */
1694 window[window_posn++] = main_element;
1695 this_run--;
1697 else {
1698 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1699 main_element -= LZX_NUM_CHARS;
1701 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1702 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1703 READ_HUFFSYM(LENGTH, length_footer);
1704 match_length += length_footer;
1706 match_length += LZX_MIN_MATCH;
1708 match_offset = main_element >> 3;
1710 if (match_offset > 2) {
1711 /* not repeated offset */
1712 extra = CAB(extra_bits)[match_offset];
1713 match_offset = CAB(lzx_position_base)[match_offset] - 2;
1714 if (extra > 3) {
1715 /* verbatim and aligned bits */
1716 extra -= 3;
1717 READ_BITS(verbatim_bits, extra);
1718 match_offset += (verbatim_bits << 3);
1719 READ_HUFFSYM(ALIGNED, aligned_bits);
1720 match_offset += aligned_bits;
1722 else if (extra == 3) {
1723 /* aligned bits only */
1724 READ_HUFFSYM(ALIGNED, aligned_bits);
1725 match_offset += aligned_bits;
1727 else if (extra > 0) { /* extra==1, extra==2 */
1728 /* verbatim bits only */
1729 READ_BITS(verbatim_bits, extra);
1730 match_offset += verbatim_bits;
1732 else /* extra == 0 */ {
1733 /* ??? */
1734 match_offset = 1;
1737 /* update repeated offset LRU queue */
1738 R2 = R1; R1 = R0; R0 = match_offset;
1740 else if (match_offset == 0) {
1741 match_offset = R0;
1743 else if (match_offset == 1) {
1744 match_offset = R1;
1745 R1 = R0; R0 = match_offset;
1747 else /* match_offset == 2 */ {
1748 match_offset = R2;
1749 R2 = R0; R0 = match_offset;
1752 rundest = window + window_posn;
1753 this_run -= match_length;
1755 /* copy any wrapped around source data */
1756 if (window_posn >= match_offset) {
1757 /* no wrap */
1758 runsrc = rundest - match_offset;
1759 } else {
1760 runsrc = rundest + (window_size - match_offset);
1761 copy_length = match_offset - window_posn;
1762 if (copy_length < match_length) {
1763 match_length -= copy_length;
1764 window_posn += copy_length;
1765 while (copy_length-- > 0) *rundest++ = *runsrc++;
1766 runsrc = window;
1769 window_posn += match_length;
1771 /* copy match data - no worries about destination wraps */
1772 while (match_length-- > 0) *rundest++ = *runsrc++;
1775 break;
1777 case LZX_BLOCKTYPE_UNCOMPRESSED:
1778 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1779 memcpy(window + window_posn, inpos, (size_t) this_run);
1780 inpos += this_run; window_posn += this_run;
1781 break;
1783 default:
1784 return DECR_ILLEGALDATA; /* might as well */
1790 if (togo != 0) return DECR_ILLEGALDATA;
1791 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1792 outlen, (size_t) outlen);
1794 LZX(window_posn) = window_posn;
1795 LZX(R0) = R0;
1796 LZX(R1) = R1;
1797 LZX(R2) = R2;
1799 /* intel E8 decoding */
1800 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1801 if (outlen <= 6 || !LZX(intel_started)) {
1802 LZX(intel_curpos) += outlen;
1804 else {
1805 cab_UBYTE *data = CAB(outbuf);
1806 cab_UBYTE *dataend = data + outlen - 10;
1807 cab_LONG curpos = LZX(intel_curpos);
1808 cab_LONG filesize = LZX(intel_filesize);
1809 cab_LONG abs_off, rel_off;
1811 LZX(intel_curpos) = curpos + outlen;
1813 while (data < dataend) {
1814 if (*data++ != 0xE8) { curpos++; continue; }
1815 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1816 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1817 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1818 data[0] = (cab_UBYTE) rel_off;
1819 data[1] = (cab_UBYTE) (rel_off >> 8);
1820 data[2] = (cab_UBYTE) (rel_off >> 16);
1821 data[3] = (cab_UBYTE) (rel_off >> 24);
1823 data += 4;
1824 curpos += 5;
1828 return DECR_OK;
1831 /**********************************************************
1832 * fdi_decomp (internal)
1834 * Decompress the requested number of bytes. If savemode is zero,
1835 * do not save the output anywhere, just plow through blocks until we
1836 * reach the specified (uncompressed) distance from the starting point,
1837 * and remember the position of the cabfile pointer (and which cabfile)
1838 * after we are done; otherwise, save the data out to CAB(filehf),
1839 * decompressing the requested number of bytes and writing them out. This
1840 * is also where we jump to additional cabinets in the case of split
1841 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1843 int fdi_decomp(struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
1844 char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
1846 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
1847 cab_UBYTE buf[cfdata_SIZEOF], *data;
1848 cab_UWORD inlen, len, outlen, cando;
1849 cab_ULONG cksum;
1850 cab_LONG err;
1851 fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
1853 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
1855 while (bytes > 0) {
1856 /* cando = the max number of bytes we can do */
1857 cando = CAB(outlen);
1858 if (cando > bytes) cando = bytes;
1860 /* if cando != 0 */
1861 if (cando && savemode)
1862 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
1864 CAB(outpos) += cando;
1865 CAB(outlen) -= cando;
1866 bytes -= cando; if (!bytes) break;
1868 /* we only get here if we emptied the output buffer */
1870 /* read data header + data */
1871 inlen = outlen = 0;
1872 while (outlen == 0) {
1873 /* read the block header, skip the reserved part */
1874 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
1875 return DECR_INPUT;
1877 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
1878 return DECR_INPUT;
1880 /* we shouldn't get blocks over CAB_INPUTMAX in size */
1881 data = CAB(inbuf) + inlen;
1882 len = EndGetI16(buf+cfdata_CompressedSize);
1883 inlen += len;
1884 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
1885 if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
1886 return DECR_INPUT;
1888 /* clear two bytes after read-in data */
1889 data[len+1] = data[len+2] = 0;
1891 /* perform checksum test on the block (if one is stored) */
1892 cksum = EndGetI32(buf+cfdata_CheckSum);
1893 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
1894 return DECR_CHECKSUM; /* checksum is wrong */
1896 outlen = EndGetI16(buf+cfdata_UncompressedSize);
1898 /* outlen=0 means this block was the last contiguous part
1899 of a split block, continued in the next cabinet */
1900 if (outlen == 0) {
1901 int pathlen, filenamelen, idx, i, cabhf;
1902 char fullpath[MAX_PATH], userpath[256];
1903 FDINOTIFICATION fdin;
1904 FDICABINETINFO fdici;
1905 char emptystring = '\0';
1906 cab_UBYTE buf2[64];
1907 int success = FALSE;
1908 struct fdi_folder *fol = NULL, *linkfol = NULL;
1909 struct fdi_file *file = NULL, *linkfile = NULL;
1911 tryanothercab:
1913 /* set up the next decomp_state... */
1914 if (!(cab->next)) {
1915 if (!cab->mii.hasnext) return DECR_INPUT;
1917 if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
1918 return DECR_NOMEMORY;
1920 ZeroMemory(cab->next, sizeof(fdi_decomp_state));
1922 /* copy pszCabPath to userpath */
1923 ZeroMemory(userpath, 256);
1924 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
1925 if (pathlen) {
1926 if (pathlen < 256) {
1927 for (i = 0; i <= pathlen; i++)
1928 userpath[i] = pszCabPath[i];
1929 } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
1932 /* initial fdintNEXT_CABINET notification */
1933 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1934 fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
1935 fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
1936 fdin.psz3 = &userpath[0];
1937 fdin.fdie = FDIERROR_NONE;
1938 fdin.pv = pvUser;
1940 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1942 do {
1944 pathlen = (userpath) ? strlen(userpath) : 0;
1945 filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
1947 /* slight overestimation here to save CPU cycles in the developer's brain */
1948 if ((pathlen + filenamelen + 3) > MAX_PATH) {
1949 ERR("MAX_PATH exceeded.\n");
1950 return DECR_ILLEGALDATA;
1953 /* paste the path and filename together */
1954 idx = 0;
1955 if (pathlen) {
1956 for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
1957 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
1959 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
1960 fullpath[idx] = '\0';
1962 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
1964 /* try to get a handle to the cabfile */
1965 cabhf = PFDI_OPEN(CAB(hfdi), fullpath, 32768, _S_IREAD | _S_IWRITE);
1966 if (cabhf == -1) {
1967 /* no file. allow the user to try again */
1968 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
1969 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1970 continue;
1973 if (cabhf == 0) {
1974 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
1975 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
1976 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1977 continue;
1980 /* check if it's really a cabfile. Note that this doesn't implement the bug */
1981 if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
1982 WARN("FDIIsCabinet failed.\n");
1983 PFDI_CLOSE(CAB(hfdi), cabhf);
1984 fdin.fdie = FDIERROR_NOT_A_CABINET;
1985 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1986 continue;
1989 if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
1990 WARN("Wrong Cabinet.\n");
1991 PFDI_CLOSE(CAB(hfdi), cabhf);
1992 fdin.fdie = FDIERROR_WRONG_CABINET;
1993 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1994 continue;
1997 break;
1999 } while (1);
2001 /* cabinet notification */
2002 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2003 fdin.setID = fdici.setID;
2004 fdin.iCabinet = fdici.iCabinet;
2005 fdin.pv = pvUser;
2006 fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2007 fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2008 fdin.psz3 = pszCabPath;
2010 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2012 cab->next->setID = fdici.setID;
2013 cab->next->iCabinet = fdici.iCabinet;
2014 cab->next->hfdi = CAB(hfdi);
2015 cab->next->filehf = CAB(filehf);
2016 cab->next->cabhf = cabhf;
2017 cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2019 cab = cab->next; /* advance to the next cabinet */
2021 /* read folders */
2022 for (i = 0; i < fdici.cFolders; i++) {
2023 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF)
2024 return DECR_INPUT;
2026 if (cab->mii.folder_resv > 0)
2027 PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2029 fol = (struct fdi_folder *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2030 if (!fol) {
2031 ERR("out of memory!\n");
2032 return DECR_NOMEMORY;
2034 ZeroMemory(fol, sizeof(struct fdi_folder));
2035 if (!(cab->firstfol)) cab->firstfol = fol;
2037 fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2038 fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2039 fol->comp_type = EndGetI16(buf2+cffold_CompType);
2041 if (linkfol)
2042 linkfol->next = fol;
2043 linkfol = fol;
2046 /* read files */
2047 for (i = 0; i < fdici.cFiles; i++) {
2048 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2049 return DECR_INPUT;
2051 file = (struct fdi_file *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2052 if (!file) {
2053 ERR("out of memory!\n");
2054 return DECR_NOMEMORY;
2056 ZeroMemory(file, sizeof(struct fdi_file));
2057 if (!(cab->firstfile)) cab->firstfile = file;
2059 file->length = EndGetI32(buf2+cffile_UncompressedSize);
2060 file->offset = EndGetI32(buf2+cffile_FolderOffset);
2061 file->index = EndGetI16(buf2+cffile_FolderIndex);
2062 file->time = EndGetI16(buf2+cffile_Time);
2063 file->date = EndGetI16(buf2+cffile_Date);
2064 file->attribs = EndGetI16(buf2+cffile_Attribs);
2065 file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2067 if (!file->filename) return DECR_INPUT;
2069 if (linkfile)
2070 linkfile->next = file;
2071 linkfile = file;
2074 } else
2075 cab = cab->next; /* advance to the next cabinet */
2077 /* iterate files -- if we encounter the continued file, process it --
2078 otherwise, jump to the label above and keep looking */
2080 for (file = cab->firstfile; (file); file = file->next) {
2081 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2082 /* check to ensure a real match */
2083 if (strcasecmp(fi->filename, file->filename) == 0) {
2084 success = TRUE;
2085 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2086 return DECR_INPUT;
2087 break;
2091 if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2092 "Wrong Cabinet" notification? */
2096 /* decompress block */
2097 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2098 return err;
2099 CAB(outlen) = outlen;
2100 CAB(outpos) = CAB(outbuf);
2103 CAB(decomp_cab) = cab;
2104 return DECR_OK;
2107 /***********************************************************************
2108 * FDICopy (CABINET.22)
2110 * Iterates through the files in the Cabinet file indicated by name and
2111 * file-location. May chain forward to additional cabinets (typically
2112 * only one) if files which begin in this Cabinet are continued in another
2113 * cabinet. For each file which is partially contained in this cabinet,
2114 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2115 * notification to the pfnfdin callback. For each file which begins in
2116 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2117 * callback, and the file is optionally decompressed and saved to disk.
2118 * Notification is not provided for files which are not at least partially
2119 * contained in the specified cabinet file.
2121 * See below for a thorough explanation of the various notification
2122 * callbacks.
2124 * PARAMS
2125 * hfdi [I] An HFDI from FDICreate
2126 * pszCabinet [I] C-style string containing the filename of the cabinet
2127 * pszCabPath [I] C-style string containing the file path of the cabinet
2128 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2129 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2130 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2131 * value: NULL.
2132 * pvUser [I] arbitrary void * value which is passed to callbacks.
2134 * RETURNS
2135 * TRUE if successful.
2136 * FALSE if unsuccessful (error information is provided in the ERF structure
2137 * associated with the provided decompression handle by FDICreate).
2139 * CALLBACKS
2141 * Two pointers to callback functions are provided as parameters to FDICopy:
2142 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2143 * types are as follows:
2145 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2146 * PFDINOTIFICATION pfdin );
2148 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2150 * You can create functions of this type using the FNFDINOTIFY() and
2151 * FNFDIDECRYPT() macros, respectively. For example:
2153 * FNFDINOTIFY(mycallback) {
2154 * / * use variables fdint and pfdin to process notification * /
2157 * The second callback, which could be used for decrypting encrypted data,
2158 * is not used at all.
2160 * Each notification informs the user of some event which has occurred during
2161 * decompression of the cabinet file; each notification is also an opportunity
2162 * for the callee to abort decompression. The information provided to the
2163 * callback and the meaning of the callback's return value vary drastically
2164 * across the various types of notification. The type of notification is the
2165 * fdint parameter; all other information is provided to the callback in
2166 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2167 * pfdin. The only part of that structure which is assigned for every callback
2168 * is the pv element, which contains the arbitrary value which was passed to
2169 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2170 * is highly dependent on fdint).
2172 * If you encounter unknown notifications, you should return zero if you want
2173 * decompression to continue (or -1 to abort). All strings used in the
2174 * callbacks are regular C-style strings. Detailed descriptions of each
2175 * notification type follow:
2177 * fdintCABINET_INFO:
2179 * This is the first notification provided after calling FDICopy, and provides
2180 * the user with various information about the cabinet. Note that this is
2181 * called for each cabinet FDICopy opens, not just the first one. In the
2182 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2183 * next cabinet file in the set after the one just loaded (if any), psz2
2184 * contains a pointer to the name or "info" of the next disk, psz3
2185 * contains a pointer to the file-path of the current cabinet, setID
2186 * contains an arbitrary constant associated with this set of cabinet files,
2187 * and iCabinet contains the numerical index of the current cabinet within
2188 * that set. Return zero, or -1 to abort.
2190 * fdintPARTIAL_FILE:
2192 * This notification is provided when FDICopy encounters a part of a file
2193 * contained in this cabinet which is missing its beginning. Files can be
2194 * split across cabinets, so this is not necessarily an abnormality; it just
2195 * means that the file in question begins in another cabinet. No file
2196 * corresponding to this notification is extracted from the cabinet. In the
2197 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2198 * partial file, psz2 contains a pointer to the file name of the cabinet in
2199 * which this file begins, and psz3 contains a pointer to the disk name or
2200 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2202 * fdintCOPY_FILE:
2204 * This notification is provided when FDICopy encounters a file which starts
2205 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2206 * look for files in cabinets after the first one). One notification will be
2207 * sent for each such file, before the file is decompressed. By returning
2208 * zero, the callback can instruct FDICopy to skip the file. In the structure
2209 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2210 * the size of the file (uncompressed), attribs contains the file attributes,
2211 * and date and time contain the date and time of the file. attributes, date,
2212 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2213 * for the entire cabinet, 0 to skip just this file but continue scanning the
2214 * cabinet for more files, or an FDIClose()-compatible file-handle.
2216 * fdintCLOSE_FILE_INFO:
2218 * This notification is important, don't forget to implement it. This
2219 * notification indicates that a file has been successfully uncompressed and
2220 * written to disk. Upon receipt of this notification, the callee is expected
2221 * to close the file handle, to set the attributes and date/time of the
2222 * closed file, and possibly to execute the file. In the structure pointed to
2223 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2224 * open file handle (close it), cb contains 1 or zero, indicating respectively
2225 * that the callee should or should not execute the file, and date, time
2226 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2227 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2228 * do so. Return TRUE, or FALSE to abort decompression.
2230 * fdintNEXT_CABINET:
2232 * This notification is called when FDICopy must load in another cabinet. This
2233 * can occur when a file's data is "split" across multiple cabinets. The
2234 * callee has the opportunity to request that FDICopy look in a different file
2235 * path for the specified cabinet file, by writing that data into a provided
2236 * buffer (see below for more information). This notification will be received
2237 * more than once per-cabinet in the instance that FDICopy failed to find a
2238 * valid cabinet at the location specified by the first per-cabinet
2239 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2240 * structure pointed to by pfdin indicates the error which prevented FDICopy
2241 * from proceeding successfully. Return zero to indicate success, or -1 to
2242 * indicate failure and abort FDICopy.
2244 * Upon receipt of this notification, the structure pointed to by pfdin will
2245 * contain the following values: psz1 pointing to the name of the cabinet
2246 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2247 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2248 * and fdie containing either FDIERROR_NONE, or one of the following:
2250 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2251 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2252 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2253 * FDIERROR_WRONG_CABINET.
2255 * The callee may choose to change the path where FDICopy will look for the
2256 * cabinet after this notification. To do so, the caller may write the new
2257 * pathname to the buffer pointed to by psz3, which is 256 characters in
2258 * length, including the terminating null character, before returning zero.
2260 * fdintENUMERATE:
2262 * Undocumented and unimplemented in wine, this seems to be sent each time
2263 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2264 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2265 * provides information about the current cabinet instead of the next one....
2266 * this is just a guess, it has not been looked at closely.
2268 * INCLUDES
2269 * fdi.c
2271 BOOL __cdecl FDICopy(
2272 HFDI hfdi,
2273 char *pszCabinet,
2274 char *pszCabPath,
2275 int flags,
2276 PFNFDINOTIFY pfnfdin,
2277 PFNFDIDECRYPT pfnfdid,
2278 void *pvUser)
2280 FDICABINETINFO fdici;
2281 FDINOTIFICATION fdin;
2282 int cabhf, filehf;
2283 int i, idx;
2284 char fullpath[MAX_PATH];
2285 size_t pathlen, filenamelen;
2286 char emptystring = '\0';
2287 cab_UBYTE buf[64];
2288 struct fdi_folder *fol = NULL, *linkfol = NULL;
2289 struct fdi_file *file = NULL, *linkfile = NULL;
2290 fdi_decomp_state _decomp_state;
2291 fdi_decomp_state *decomp_state = &_decomp_state;
2293 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, \
2294 pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2295 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2297 if (!REALLY_IS_FDI(hfdi)) {
2298 SetLastError(ERROR_INVALID_HANDLE);
2299 return FALSE;
2302 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2304 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2305 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2307 /* slight overestimation here to save CPU cycles in the developer's brain */
2308 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2309 ERR("MAX_PATH exceeded.\n");
2310 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2311 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2312 PFDI_INT(hfdi)->perf->fError = TRUE;
2313 SetLastError(ERROR_FILE_NOT_FOUND);
2314 return FALSE;
2317 /* paste the path and filename together */
2318 idx = 0;
2319 if (pathlen) {
2320 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2321 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2323 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2324 fullpath[idx] = '\0';
2326 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2328 /* get a handle to the cabfile */
2329 cabhf = PFDI_OPEN(hfdi, fullpath, 32768, _S_IREAD | _S_IWRITE);
2330 if (cabhf == -1) {
2331 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2332 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2333 PFDI_INT(hfdi)->perf->fError = TRUE;
2334 SetLastError(ERROR_FILE_NOT_FOUND);
2335 return FALSE;
2338 if (cabhf == 0) {
2339 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2340 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2341 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2342 PFDI_INT(hfdi)->perf->fError = TRUE;
2343 SetLastError(ERROR_FILE_NOT_FOUND);
2344 return FALSE;
2347 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2348 if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2349 ERR("FDIIsCabinet failed.\n");
2350 PFDI_CLOSE(hfdi, cabhf);
2351 return FALSE;
2354 /* cabinet notification */
2355 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2356 fdin.setID = fdici.setID;
2357 fdin.iCabinet = fdici.iCabinet;
2358 fdin.pv = pvUser;
2359 fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2360 fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2361 fdin.psz3 = pszCabPath;
2363 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2364 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2365 PFDI_INT(hfdi)->perf->erfType = 0;
2366 PFDI_INT(hfdi)->perf->fError = TRUE;
2367 goto bail_and_fail;
2370 CAB(setID) = fdici.setID;
2371 CAB(iCabinet) = fdici.iCabinet;
2373 /* read folders */
2374 for (i = 0; i < fdici.cFolders; i++) {
2375 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2376 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2377 PFDI_INT(hfdi)->perf->erfType = 0;
2378 PFDI_INT(hfdi)->perf->fError = TRUE;
2379 goto bail_and_fail;
2382 if (CAB(mii).folder_resv > 0)
2383 PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2385 fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2386 if (!fol) {
2387 ERR("out of memory!\n");
2388 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2389 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2390 PFDI_INT(hfdi)->perf->fError = TRUE;
2391 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2392 goto bail_and_fail;
2394 ZeroMemory(fol, sizeof(struct fdi_folder));
2395 if (!CAB(firstfol)) CAB(firstfol) = fol;
2397 fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2398 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2399 fol->comp_type = EndGetI16(buf+cffold_CompType);
2401 if (linkfol)
2402 linkfol->next = fol;
2403 linkfol = fol;
2406 /* read files */
2407 for (i = 0; i < fdici.cFiles; i++) {
2408 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2409 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2410 PFDI_INT(hfdi)->perf->erfType = 0;
2411 PFDI_INT(hfdi)->perf->fError = TRUE;
2412 goto bail_and_fail;
2415 file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2416 if (!file) {
2417 ERR("out of memory!\n");
2418 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2419 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2420 PFDI_INT(hfdi)->perf->fError = TRUE;
2421 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2422 goto bail_and_fail;
2424 ZeroMemory(file, sizeof(struct fdi_file));
2425 if (!CAB(firstfile)) CAB(firstfile) = file;
2427 file->length = EndGetI32(buf+cffile_UncompressedSize);
2428 file->offset = EndGetI32(buf+cffile_FolderOffset);
2429 file->index = EndGetI16(buf+cffile_FolderIndex);
2430 file->time = EndGetI16(buf+cffile_Time);
2431 file->date = EndGetI16(buf+cffile_Date);
2432 file->attribs = EndGetI16(buf+cffile_Attribs);
2433 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2435 if (!file->filename) {
2436 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2437 PFDI_INT(hfdi)->perf->erfType = 0;
2438 PFDI_INT(hfdi)->perf->fError = TRUE;
2439 goto bail_and_fail;
2442 if (linkfile)
2443 linkfile->next = file;
2444 linkfile = file;
2447 for (file = CAB(firstfile); (file); file = file->next) {
2450 * FIXME: This implementation keeps multiple cabinet files open at once
2451 * when encountering a split cabinet. It is a quirk of this implementation
2452 * that sometimes we decrypt the same block of data more than once, to find
2453 * the right starting point for a file, moving the file-pointer backwards.
2454 * If we kept a cache of certain file-pointer information, we could eliminate
2455 * that behavior... in fact I am not sure that the caching we already have
2456 * is not sufficient.
2458 * The current implementation seems to work fine in straightforward situations
2459 * where all the cabinet files needed for decryption are simultaneously
2460 * available. But presumably, the API is supposed to support cabinets which
2461 * are split across multiple CDROMS; we may need to change our implementation
2462 * to strictly serialize it's file usage so that it opens only one cabinet
2463 * at a time. Some experimentation with Windows is needed to figure out the
2464 * precise semantics required. The relevant code is here and in fdi_decomp().
2467 /* partial-file notification */
2468 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2470 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2471 * and perform some tests to figure out the right behavior. The SDK says
2472 * FDICopy will notify the user of the filename and "disk name" (info) of
2473 * the cabinet where the spanning file /started/.
2475 * That would certainly be convenient for the API-user, who could abort,
2476 * everything (or parallelize, if that's allowed (it is in wine)), and call
2477 * FDICopy again with the provided filename, so as to avoid partial file
2478 * notification and successfully unpack. This task could be quite unpleasant
2479 * from wine's perspective: the information specifying the "start cabinet" for
2480 * a file is associated nowhere with the file header and is not to be found in
2481 * the cabinet header. We have only the index of the cabinet wherein the folder
2482 * begins, which contains the file. To find that cabinet, we must consider the
2483 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2484 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2485 * list).
2487 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2488 * cabinet other than the active one might be at another filepath than the
2489 * current one, or on another CDROM. This could get rather dicey, especially
2490 * if we imagine parallelized access to the FDICopy API.
2492 * The current implementation punts -- it just returns the previous cabinet and
2493 * it's info from the header of this cabinet. This provides the right answer in
2494 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2495 * we "fix" it.
2497 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2498 fdin.pv = pvUser;
2499 fdin.psz1 = (char *)file->filename;
2500 fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2501 fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2503 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2504 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2505 PFDI_INT(hfdi)->perf->erfType = 0;
2506 PFDI_INT(hfdi)->perf->fError = TRUE;
2507 goto bail_and_fail;
2509 /* I don't think we are supposed to decompress partial files. This prevents it. */
2510 file->oppressed = TRUE;
2512 if (file->oppressed) {
2513 filehf = 0;
2514 } else {
2515 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2516 fdin.pv = pvUser;
2517 fdin.psz1 = (char *)file->filename;
2518 fdin.cb = file->length;
2519 fdin.date = file->date;
2520 fdin.time = file->time;
2521 fdin.attribs = file->attribs;
2522 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2523 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2524 PFDI_INT(hfdi)->perf->erfType = 0;
2525 PFDI_INT(hfdi)->perf->fError = TRUE;
2526 goto bail_and_fail;
2530 /* find the folder for this file if necc. */
2531 if (filehf) {
2532 int i2;
2534 fol = CAB(firstfol);
2535 if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2536 /* pick the last folder */
2537 while (fol->next) fol = fol->next;
2538 } else {
2539 for (i2 = 0; (i2 < file->index); i2++)
2540 if (fol->next) /* bug resistance, should always be true */
2541 fol = fol->next;
2545 if (filehf) {
2546 cab_UWORD comptype = fol->comp_type;
2547 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2548 int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2549 int err = 0;
2551 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2553 /* set up decomp_state */
2554 CAB(hfdi) = hfdi;
2555 CAB(filehf) = filehf;
2556 CAB(cabhf) = cabhf;
2558 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2559 if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2561 TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2563 /* free stuff for the old decompresser */
2564 switch (ct2) {
2565 case cffoldCOMPTYPE_LZX:
2566 if (LZX(window)) {
2567 PFDI_FREE(hfdi, LZX(window));
2568 LZX(window) = NULL;
2570 break;
2571 case cffoldCOMPTYPE_QUANTUM:
2572 if (QTM(window)) {
2573 PFDI_FREE(hfdi, QTM(window));
2574 QTM(window) = NULL;
2576 break;
2579 CAB(decomp_cab) = NULL;
2580 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2581 CAB(offset) = 0;
2582 CAB(outlen) = 0;
2584 /* initialize the new decompresser */
2585 switch (ct1) {
2586 case cffoldCOMPTYPE_NONE:
2587 CAB(decompress) = NONEfdi_decomp;
2588 break;
2589 case cffoldCOMPTYPE_MSZIP:
2590 CAB(decompress) = ZIPfdi_decomp;
2591 break;
2592 case cffoldCOMPTYPE_QUANTUM:
2593 CAB(decompress) = QTMfdi_decomp;
2594 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2595 break;
2596 case cffoldCOMPTYPE_LZX:
2597 CAB(decompress) = LZXfdi_decomp;
2598 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2599 break;
2600 default:
2601 err = DECR_DATAFORMAT;
2605 CAB(current) = fol;
2607 switch (err) {
2608 case DECR_OK:
2609 break;
2610 case DECR_NOMEMORY:
2611 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2612 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2613 PFDI_INT(hfdi)->perf->fError = TRUE;
2614 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2615 goto bail_and_fail;
2616 default:
2617 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2618 PFDI_INT(hfdi)->perf->erfOper = 0;
2619 PFDI_INT(hfdi)->perf->fError = TRUE;
2620 goto bail_and_fail;
2623 if (file->offset > CAB(offset)) {
2624 /* decode bytes and send them to /dev/null */
2625 switch ((err = fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser))) {
2626 case DECR_OK:
2627 break;
2628 case DECR_USERABORT:
2629 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2630 PFDI_INT(hfdi)->perf->erfType = 0;
2631 PFDI_INT(hfdi)->perf->fError = TRUE;
2632 goto bail_and_fail;
2633 case DECR_NOMEMORY:
2634 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2635 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2636 PFDI_INT(hfdi)->perf->fError = TRUE;
2637 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2638 goto bail_and_fail;
2639 default:
2640 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2641 PFDI_INT(hfdi)->perf->erfOper = 0;
2642 PFDI_INT(hfdi)->perf->fError = TRUE;
2643 goto bail_and_fail;
2645 CAB(offset) = file->offset;
2648 /* now do the actual decompression */
2649 err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2650 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2652 switch (err) {
2653 case DECR_OK:
2654 break;
2655 case DECR_USERABORT:
2656 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2657 PFDI_INT(hfdi)->perf->erfType = 0;
2658 PFDI_INT(hfdi)->perf->fError = TRUE;
2659 goto bail_and_fail;
2660 case DECR_NOMEMORY:
2661 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2662 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2663 PFDI_INT(hfdi)->perf->fError = TRUE;
2664 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2665 goto bail_and_fail;
2666 default:
2667 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2668 PFDI_INT(hfdi)->perf->erfOper = 0;
2669 PFDI_INT(hfdi)->perf->fError = TRUE;
2670 goto bail_and_fail;
2673 /* fdintCLOSE_FILE_INFO notification */
2674 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2675 fdin.pv = pvUser;
2676 fdin.psz1 = (char *)file->filename;
2677 fdin.hf = filehf;
2678 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2679 fdin.date = file->date;
2680 fdin.time = file->time;
2681 fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2682 err = ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2683 if (err == FALSE || err == -1) {
2685 * SDK states that even though they indicated failure,
2686 * we are not supposed to try and close the file, so we
2687 * just treat this like all the others
2689 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2690 PFDI_INT(hfdi)->perf->erfType = 0;
2691 PFDI_INT(hfdi)->perf->fError = TRUE;
2692 goto bail_and_fail;
2697 /* free decompression temps */
2698 if (LZX(window)) {
2699 PFDI_FREE(hfdi, LZX(window));
2700 LZX(window) = NULL;
2702 if (QTM(window)) {
2703 PFDI_FREE(hfdi, QTM(window));
2704 QTM(window) = NULL;
2707 while (decomp_state) {
2708 fdi_decomp_state *prev_fds;
2710 PFDI_CLOSE(hfdi, CAB(cabhf));
2712 /* free the storage remembered by mii */
2713 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2714 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2715 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2716 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2718 while (CAB(firstfol)) {
2719 fol = CAB(firstfol);
2720 CAB(firstfol) = CAB(firstfol)->next;
2721 PFDI_FREE(hfdi, fol);
2723 while (CAB(firstfile)) {
2724 file = CAB(firstfile);
2725 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2726 CAB(firstfile) = CAB(firstfile)->next;
2727 PFDI_FREE(hfdi, file);
2729 prev_fds = decomp_state;
2730 decomp_state = CAB(next);
2731 if (prev_fds != &_decomp_state)
2732 PFDI_FREE(hfdi, prev_fds);
2735 return TRUE;
2737 bail_and_fail: /* here we free ram before error returns */
2739 /* free decompression temps */
2740 if (LZX(window)) {
2741 PFDI_FREE(hfdi, LZX(window));
2742 LZX(window) = NULL;
2744 if (QTM(window)) {
2745 PFDI_FREE(hfdi, QTM(window));
2746 QTM(window) = NULL;
2749 while (decomp_state) {
2750 fdi_decomp_state *prev_fds;
2752 PFDI_CLOSE(hfdi, CAB(cabhf));
2754 /* free the storage remembered by mii */
2755 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2756 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2757 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2758 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2760 while (CAB(firstfol)) {
2761 fol = CAB(firstfol);
2762 CAB(firstfol) = CAB(firstfol)->next;
2763 PFDI_FREE(hfdi, fol);
2765 while (CAB(firstfile)) {
2766 file = CAB(firstfile);
2767 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2768 CAB(firstfile) = CAB(firstfile)->next;
2769 PFDI_FREE(hfdi, file);
2771 prev_fds = decomp_state;
2772 decomp_state = CAB(next);
2773 if (prev_fds != &_decomp_state)
2774 PFDI_FREE(hfdi, prev_fds);
2777 return FALSE;
2780 /***********************************************************************
2781 * FDIDestroy (CABINET.23)
2783 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2784 * of FDICopy. Only reason for failure would be an invalid handle.
2786 * PARAMS
2787 * hfdi [I] The HFDI to free
2789 * RETURNS
2790 * TRUE for success
2791 * FALSE for failure
2793 BOOL __cdecl FDIDestroy(HFDI hfdi)
2795 TRACE("(hfdi == ^%p)\n", hfdi);
2796 if (REALLY_IS_FDI(hfdi)) {
2797 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2798 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2799 return TRUE;
2800 } else {
2801 SetLastError(ERROR_INVALID_HANDLE);
2802 return FALSE;
2806 /***********************************************************************
2807 * FDITruncateCabinet (CABINET.24)
2809 * Undocumented and unimplemented.
2811 BOOL __cdecl FDITruncateCabinet(
2812 HFDI hfdi,
2813 char *pszCabinetName,
2814 USHORT iFolderToDelete)
2816 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2817 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2819 if (!REALLY_IS_FDI(hfdi)) {
2820 SetLastError(ERROR_INVALID_HANDLE);
2821 return FALSE;
2824 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2825 return FALSE;