Typos/spelling fixes.
[wine/gsoc_dplay.git] / dlls / cabinet / fdi.c
blobf8f1b3c076e357b8e0fa61c2ad281dcefa5a4cab
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 (or will be) a largely redundant reimplementation of the stuff in
24 * cabextract.c... it would theoretically be preferable to have only one, shared
25 * implementation, however there are semantic differences which may discourage efforts
26 * to unify the two. It should be possible, if awkward, to go back and reimplement
27 * cabextract.c using FDI (once the FDI implementation is complete, of course).
28 * -gmt
31 #include "config.h"
33 #include <stdio.h>
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winerror.h"
38 #include "fdi.h"
39 #include "msvcrt/fcntl.h" /* _O_.* */
40 #include "cabinet.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
46 THOSE_ZIP_CONSTS;
48 struct fdi_file {
49 struct fdi_file *next; /* next file in sequence */
50 struct fdi_folder *folder; /* folder that contains this file */
51 LPCSTR filename; /* output name of file */
52 int fh; /* open file handle or NULL */
53 cab_ULONG length; /* uncompressed length of file */
54 cab_ULONG offset; /* uncompressed offset in folder */
55 cab_UWORD index; /* magic index number of folder */
56 cab_UWORD time, date, attribs; /* MS-DOS time/date/attributes */
57 BOOL oppressed; /* never to be processed */
60 struct fdi_folder {
61 struct fdi_folder *next;
62 cab_off_t offset[CAB_SPLITMAX]; /* offset to data blocks (32 bit) */
63 cab_UWORD comp_type; /* compression format/window size */
64 cab_ULONG comp_size; /* compressed size of folder */
65 cab_UBYTE num_splits; /* number of split blocks + 1 */
66 cab_UWORD num_blocks; /* total number of blocks */
67 struct fdi_file *contfile; /* the first split file */
71 * ugh, well, this ended up being pretty damn silly...
72 * now that I've conceeded to build equivalent structures to struct cab.*,
73 * I should have just used those, or, better yet, unified the two... sue me.
74 * (Note to Microsoft: That's a joke. Please /don't/ actually sue me! -gmt).
75 * Nevertheless, I've come this far, it works, so I'm not gonna change it
76 * for now.
79 typedef struct fdi_cds_fwd {
80 void *hfdi; /* the hfdi we are using */
81 int filehf, cabhf; /* file handle we are using */
82 struct fdi_folder *current; /* current folder we're extracting from */
83 cab_UBYTE block_resv;
84 cab_ULONG offset; /* uncompressed offset within folder */
85 cab_UBYTE *outpos; /* (high level) start of data to use up */
86 cab_UWORD outlen; /* (high level) amount of data to use up */
87 cab_UWORD split; /* at which split in current folder? */
88 int (*decompress)(int, int, struct fdi_cds_fwd *); /* chosen compress fn */
89 cab_UBYTE inbuf[CAB_INPUTMAX+2]; /* +2 for lzx bitbuffer overflows! */
90 cab_UBYTE outbuf[CAB_BLOCKMAX];
91 union {
92 struct ZIPstate zip;
93 struct QTMstate qtm;
94 struct LZXstate lzx;
95 } methods;
96 } fdi_decomp_state;
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.
103 typedef struct {
104 char *prevname, *previnfo;
105 char *nextname, *nextinfo;
106 int folder_resv, header_resv;
107 cab_UBYTE block_resv;
108 } MORE_ISCAB_INFO, *PMORE_ISCAB_INFO;
110 /***********************************************************************
111 * FDICreate (CABINET.20)
113 HFDI __cdecl FDICreate(
114 PFNALLOC pfnalloc,
115 PFNFREE pfnfree,
116 PFNOPEN pfnopen,
117 PFNREAD pfnread,
118 PFNWRITE pfnwrite,
119 PFNCLOSE pfnclose,
120 PFNSEEK pfnseek,
121 int cpuType,
122 PERF perf)
124 HFDI rv;
126 TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, \
127 pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
128 pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
129 cpuType, perf);
131 /* PONDERME: Certainly, we cannot tolerate a missing pfnalloc, as we call it just below.
132 pfnfree is tested as well, for symmetry. As for the rest, should we test these
133 too? In a vacuum, I would say yes... but does Windows care? If not, then, I guess,
134 neither do we.... */
135 if ((!pfnalloc) || (!pfnfree)) {
136 perf->erfOper = FDIERROR_NONE;
137 perf->erfType = ERROR_BAD_ARGUMENTS;
138 perf->fError = TRUE;
140 SetLastError(ERROR_BAD_ARGUMENTS);
141 return NULL;
144 if (!((rv = ((HFDI) (*pfnalloc)(sizeof(FDI_Int)))))) {
145 perf->erfOper = FDIERROR_ALLOC_FAIL;
146 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
147 perf->fError = TRUE;
149 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
150 return NULL;
153 PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
154 PFDI_INT(rv)->pfnalloc = pfnalloc;
155 PFDI_INT(rv)->pfnfree = pfnfree;
156 PFDI_INT(rv)->pfnopen = pfnopen;
157 PFDI_INT(rv)->pfnread = pfnread;
158 PFDI_INT(rv)->pfnwrite = pfnwrite;
159 PFDI_INT(rv)->pfnclose = pfnclose;
160 PFDI_INT(rv)->pfnseek = pfnseek;
161 /* no-brainer: we ignore the cpu type; this is only used
162 for the 16-bit versions in Windows anyhow... */
163 PFDI_INT(rv)->perf = perf;
165 return rv;
168 /*******************************************************************
169 * FDI_getoffset (internal)
171 * returns the file pointer position of a cab
173 long FDI_getoffset(HFDI hfdi, INT_PTR hf)
175 return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
178 /**********************************************************************
179 * FDI_realloc (internal)
181 * we can't use _msize; the user might not be using malloc, so we require
182 * an explicit specification of the previous size. utterly inefficient.
184 void *FDI_realloc(HFDI hfdi, void *mem, size_t prevsize, size_t newsize)
186 void *rslt = NULL;
187 char *irslt, *imem;
188 size_t copysize = (prevsize < newsize) ? prevsize : newsize;
189 if (prevsize == newsize) return mem;
190 rslt = PFDI_ALLOC(hfdi, newsize);
191 if (rslt)
192 for (irslt = (char *)rslt, imem = (char *)mem; (copysize); copysize--)
193 *irslt++ = *imem++;
194 PFDI_FREE(hfdi, mem);
195 return rslt;
198 /**********************************************************************
199 * FDI_read_string (internal)
201 * allocate and read an aribitrarily long string from the cabinet
203 char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
205 size_t len=256,
206 oldlen = 0,
207 base = FDI_getoffset(hfdi, hf),
208 maxlen = cabsize - base;
209 BOOL ok = FALSE;
210 int i;
211 cab_UBYTE *buf = NULL;
213 TRACE("(hfdi == ^%p, hf == %d)\n", hfdi, hf);
215 do {
216 if (len > maxlen) len = maxlen;
217 if (!(buf = FDI_realloc(hfdi, buf, oldlen, len))) break;
218 oldlen = len;
219 if (!PFDI_READ(hfdi, hf, buf, len)) break;
221 /* search for a null terminator in what we've just read */
222 for (i=0; i < len; i++) {
223 if (!buf[i]) {ok=TRUE; break;}
226 if (!ok) {
227 if (len == maxlen) {
228 ERR("WARNING: cabinet is truncated\n");
229 break;
231 len += 256;
232 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
234 } while (!ok);
236 if (!ok) {
237 if (buf)
238 PFDI_FREE(hfdi, buf);
239 else
240 ERR("out of memory!\n");
241 return NULL;
244 /* otherwise, set the stream to just after the string and return */
245 PFDI_SEEK(hfdi, hf, base + ((cab_off_t) strlen((char *) buf)) + 1, SEEK_SET);
247 return (char *) buf;
250 /******************************************************************
251 * FDI_read_entries (internal)
253 * process the cabinet header in the style of FDIIsCabinet, but
254 * without the sanity checks (and bug)
256 * if pmii is non-null, some info not expressed in FDICABINETINFO struct
257 * will be stored there... responsibility to free the enclosed stuff is
258 * delegated to the caller in this case.
260 BOOL FDI_read_entries(
261 HFDI hfdi,
262 INT_PTR hf,
263 PFDICABINETINFO pfdici,
264 PMORE_ISCAB_INFO pmii)
266 int num_folders, num_files, header_resv, folder_resv = 0;
267 LONG base_offset, cabsize;
268 USHORT setid, cabidx, flags;
269 cab_UBYTE buf[64], block_resv;
270 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
272 TRACE("(hfdi == ^%p, hf == %d, pfdici == ^%p)\n", hfdi, hf, pfdici);
274 if (pmii) ZeroMemory(pmii, sizeof(MORE_ISCAB_INFO));
276 /* get basic offset & size info */
277 base_offset = FDI_getoffset(hfdi, hf);
279 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
280 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
281 PFDI_INT(hfdi)->perf->erfType = 0;
282 PFDI_INT(hfdi)->perf->fError = TRUE;
283 return FALSE;
286 cabsize = FDI_getoffset(hfdi, hf);
288 if ((cabsize == -1) || (base_offset == -1) ||
289 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
290 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
291 PFDI_INT(hfdi)->perf->erfType = 0;
292 PFDI_INT(hfdi)->perf->fError = TRUE;
293 return FALSE;
296 /* read in the CFHEADER */
297 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
298 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
299 PFDI_INT(hfdi)->perf->erfType = 0;
300 PFDI_INT(hfdi)->perf->fError = TRUE;
301 return FALSE;
304 /* check basic MSCF signature */
305 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
306 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
307 PFDI_INT(hfdi)->perf->erfType = 0;
308 PFDI_INT(hfdi)->perf->fError = TRUE;
309 return FALSE;
312 /* get the number of folders */
313 num_folders = EndGetI16(buf+cfhead_NumFolders);
314 if (num_folders == 0) {
315 /* PONDERME: is this really invalid? */
316 WARN("weird cabinet detect failure: no folders in cabinet\n");
317 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
318 PFDI_INT(hfdi)->perf->erfType = 0;
319 PFDI_INT(hfdi)->perf->fError = TRUE;
320 return FALSE;
323 /* get the number of files */
324 num_files = EndGetI16(buf+cfhead_NumFiles);
325 if (num_files == 0) {
326 /* PONDERME: is this really invalid? */
327 WARN("weird cabinet detect failure: no files in cabinet\n");
328 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
329 PFDI_INT(hfdi)->perf->erfType = 0;
330 PFDI_INT(hfdi)->perf->fError = TRUE;
331 return FALSE;
334 /* setid */
335 setid = EndGetI16(buf+cfhead_SetID);
337 /* cabinet (set) index */
338 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
340 /* check the header revision */
341 if ((buf[cfhead_MajorVersion] > 1) ||
342 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
344 WARN("cabinet format version > 1.3\n");
345 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
346 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
347 PFDI_INT(hfdi)->perf->fError = TRUE;
348 return FALSE;
351 /* pull the flags out */
352 flags = EndGetI16(buf+cfhead_Flags);
354 /* read the reserved-sizes part of header, if present */
355 if (flags & cfheadRESERVE_PRESENT) {
356 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
357 ERR("bunk reserve-sizes?\n");
358 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
359 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
360 PFDI_INT(hfdi)->perf->fError = TRUE;
361 return FALSE;
364 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
365 if (pmii) pmii->header_resv = header_resv;
366 folder_resv = buf[cfheadext_FolderReserved];
367 if (pmii) pmii->folder_resv = folder_resv;
368 block_resv = buf[cfheadext_DataReserved];
369 if (pmii) pmii->block_resv = block_resv;
371 if (header_resv > 60000) {
372 WARN("WARNING; header reserved space > 60000\n");
375 /* skip the reserved header */
376 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
377 ERR("seek failure: header_resv\n");
378 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
379 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
380 PFDI_INT(hfdi)->perf->fError = TRUE;
381 return FALSE;
385 if (flags & cfheadPREV_CABINET) {
386 prevname = FDI_read_string(hfdi, hf, cabsize);
387 if (!prevname) {
388 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
389 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
390 PFDI_INT(hfdi)->perf->fError = TRUE;
391 return FALSE;
392 } else
393 if (pmii)
394 pmii->prevname = prevname;
395 else
396 PFDI_FREE(hfdi, prevname);
397 previnfo = FDI_read_string(hfdi, hf, cabsize);
398 if (previnfo) {
399 if (pmii)
400 pmii->previnfo = previnfo;
401 else
402 PFDI_FREE(hfdi, previnfo);
406 if (flags & cfheadNEXT_CABINET) {
407 nextname = FDI_read_string(hfdi, hf, cabsize);
408 if (!nextname) {
409 if ((flags & cfheadPREV_CABINET) && pmii) {
410 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
411 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
413 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
414 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
415 PFDI_INT(hfdi)->perf->fError = TRUE;
416 return FALSE;
417 } else
418 if (pmii)
419 pmii->nextname = nextname;
420 else
421 PFDI_FREE(hfdi, nextname);
422 nextinfo = FDI_read_string(hfdi, hf, cabsize);
423 if (nextinfo) {
424 if (pmii)
425 pmii->nextinfo = nextinfo;
426 else
427 PFDI_FREE(hfdi, nextinfo);
431 /* we could process the whole cabinet searching for problems;
432 instead lets stop here. Now let's fill out the paperwork */
433 pfdici->cbCabinet = cabsize;
434 pfdici->cFolders = num_folders;
435 pfdici->cFiles = num_files;
436 pfdici->setID = setid;
437 pfdici->iCabinet = cabidx;
438 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
439 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
440 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
441 return TRUE;
444 /***********************************************************************
445 * FDIIsCabinet (CABINET.21)
447 BOOL __cdecl FDIIsCabinet(
448 HFDI hfdi,
449 INT_PTR hf,
450 PFDICABINETINFO pfdici)
452 BOOL rv;
454 TRACE("(hfdi == ^%p, hf == ^%d, pfdici == ^%p)\n", hfdi, hf, pfdici);
456 if (!REALLY_IS_FDI(hfdi)) {
457 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
458 SetLastError(ERROR_INVALID_HANDLE);
459 return FALSE;
462 if (!hf) {
463 ERR("(!hf)!\n");
464 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
465 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
466 PFDI_INT(hfdi)->perf->fError = TRUE;
467 SetLastError(ERROR_INVALID_HANDLE);
468 return FALSE;
471 if (!pfdici) {
472 ERR("(!pfdici)!\n");
473 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
474 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
475 PFDI_INT(hfdi)->perf->fError = TRUE;
476 SetLastError(ERROR_BAD_ARGUMENTS);
477 return FALSE;
479 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
481 if (rv)
482 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
484 return rv;
487 /* FIXME: eliminate global variables */
488 static cab_UBYTE q_length_base[27], q_length_extra[27], q_extra_bits[42];
489 static cab_ULONG q_position_base[42];
491 /******************************************************************
492 * QTMfdi_initmodel (internal)
494 * Initialise a model which decodes symbols from [s] to [s]+[n]-1
496 void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
497 int i;
498 m->shiftsleft = 4;
499 m->entries = n;
500 m->syms = sym;
501 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
502 for (i = 0; i < n; i++) {
503 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
504 m->syms[i].sym = i+s; /* actual symbol */
505 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
507 m->syms[n].cumfreq = 0;
510 /******************************************************************
511 * QTMfdi_init (internal)
513 int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
514 int wndsize = 1 << window, msz = window * 2, i;
515 cab_ULONG j;
517 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
518 /* if a previously allocated window is big enough, keep it */
519 if (window < 10 || window > 21) return DECR_DATAFORMAT;
520 if (QTM(actual_size) < wndsize) {
521 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
522 QTM(window) = NULL;
524 if (!QTM(window)) {
525 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
526 QTM(actual_size) = wndsize;
528 QTM(window_size) = wndsize;
529 QTM(window_posn) = 0;
531 /* initialise static slot/extrabits tables */
532 for (i = 0, j = 0; i < 27; i++) {
533 q_length_extra[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
534 q_length_base[i] = j; j += 1 << ((i == 26) ? 5 : q_length_extra[i]);
536 for (i = 0, j = 0; i < 42; i++) {
537 q_extra_bits[i] = (i < 2 ? 0 : i-2) >> 1;
538 q_position_base[i] = j; j += 1 << q_extra_bits[i];
541 /* initialise arithmetic coding models */
543 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
545 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
546 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
547 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
548 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
550 /* model 4 depends on table size, ranges from 20 to 24 */
551 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
552 /* model 5 depends on table size, ranges from 20 to 36 */
553 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
554 /* model 6pos depends on table size, ranges from 20 to 42 */
555 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
556 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
558 return DECR_OK;
561 /* FIXME: Eliminate global variables */
562 static cab_ULONG lzx_position_base[51];
563 static cab_UBYTE extra_bits[51];
565 /************************************************************
566 * LZXfdi_init (internal)
568 int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
569 cab_ULONG wndsize = 1 << window;
570 int i, j, posn_slots;
572 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
573 /* if a previously allocated window is big enough, keep it */
574 if (window < 15 || window > 21) return DECR_DATAFORMAT;
575 if (LZX(actual_size) < wndsize) {
576 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
577 LZX(window) = NULL;
579 if (!LZX(window)) {
580 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
581 LZX(actual_size) = wndsize;
583 LZX(window_size) = wndsize;
585 /* initialise static tables */
586 for (i=0, j=0; i <= 50; i += 2) {
587 extra_bits[i] = extra_bits[i+1] = j; /* 0,0,0,0,1,1,2,2,3,3... */
588 if ((i != 0) && (j < 17)) j++; /* 0,0,1,2,3,4...15,16,17,17,17,17... */
590 for (i=0, j=0; i <= 50; i++) {
591 lzx_position_base[i] = j; /* 0,1,2,3,4,6,8,12,16,24,32,... */
592 j += 1 << extra_bits[i]; /* 1,1,1,1,2,2,4,4,8,8,16,16,32,32,... */
595 /* calculate required position slots */
596 if (window == 20) posn_slots = 42;
597 else if (window == 21) posn_slots = 50;
598 else posn_slots = window << 1;
600 /*posn_slots=i=0; while (i < wndsize) i += 1 << extra_bits[posn_slots++]; */
602 LZX(R0) = LZX(R1) = LZX(R2) = 1;
603 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
604 LZX(header_read) = 0;
605 LZX(frames_read) = 0;
606 LZX(block_remaining) = 0;
607 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
608 LZX(intel_curpos) = 0;
609 LZX(intel_started) = 0;
610 LZX(window_posn) = 0;
612 /* initialise tables to 0 (because deltas will be applied to them) */
613 for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) LZX(MAINTREE_len)[i] = 0;
614 for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) LZX(LENGTH_len)[i] = 0;
616 return DECR_OK;
619 /****************************************************
620 * NONEfdi_decomp(internal)
622 int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
624 if (inlen != outlen) return DECR_ILLEGALDATA;
625 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
626 return DECR_OK;
629 /********************************************************
630 * Ziphuft_free (internal)
632 void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
634 register struct Ziphuft *p, *q;
636 /* Go through linked list, freeing from the allocated (t[-1]) address. */
637 p = t;
638 while (p != (struct Ziphuft *)NULL)
640 q = (--p)->v.t;
641 PFDI_FREE(hfdi, p);
642 p = q;
646 /*********************************************************
647 * fdi_Ziphuft_build (internal)
649 cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, cab_UWORD *d, cab_UWORD *e,
650 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
652 cab_ULONG a; /* counter for codes of length k */
653 cab_ULONG el; /* length of EOB code (value 256) */
654 cab_ULONG f; /* i repeats in table every f entries */
655 cab_LONG g; /* maximum code length */
656 cab_LONG h; /* table level */
657 register cab_ULONG i; /* counter, current code */
658 register cab_ULONG j; /* counter */
659 register cab_LONG k; /* number of bits in current code */
660 cab_LONG *l; /* stack of bits per table */
661 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
662 register struct Ziphuft *q; /* points to current table */
663 struct Ziphuft r; /* table entry for structure assignment */
664 register cab_LONG w; /* bits before this table == (l * h) */
665 cab_ULONG *xp; /* pointer into x */
666 cab_LONG y; /* number of dummy codes added */
667 cab_ULONG z; /* number of entries in current table */
669 l = ZIP(lx)+1;
671 /* Generate counts for each bit length */
672 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
674 for(i = 0; i < ZIPBMAX+1; ++i)
675 ZIP(c)[i] = 0;
676 p = b; i = n;
679 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
680 } while (--i);
681 if (ZIP(c)[0] == n) /* null input--all zero length codes */
683 *t = (struct Ziphuft *)NULL;
684 *m = 0;
685 return 0;
688 /* Find minimum and maximum length, bound *m by those */
689 for (j = 1; j <= ZIPBMAX; j++)
690 if (ZIP(c)[j])
691 break;
692 k = j; /* minimum code length */
693 if ((cab_ULONG)*m < j)
694 *m = j;
695 for (i = ZIPBMAX; i; i--)
696 if (ZIP(c)[i])
697 break;
698 g = i; /* maximum code length */
699 if ((cab_ULONG)*m > i)
700 *m = i;
702 /* Adjust last length count to fill out codes, if needed */
703 for (y = 1 << j; j < i; j++, y <<= 1)
704 if ((y -= ZIP(c)[j]) < 0)
705 return 2; /* bad input: more codes than bits */
706 if ((y -= ZIP(c)[i]) < 0)
707 return 2;
708 ZIP(c)[i] += y;
710 /* Generate starting offsets LONGo the value table for each length */
711 ZIP(x)[1] = j = 0;
712 p = ZIP(c) + 1; xp = ZIP(x) + 2;
713 while (--i)
714 { /* note that i == g from above */
715 *xp++ = (j += *p++);
718 /* Make a table of values in order of bit lengths */
719 p = b; i = 0;
721 if ((j = *p++) != 0)
722 ZIP(v)[ZIP(x)[j]++] = i;
723 } while (++i < n);
726 /* Generate the Huffman codes and for each, make the table entries */
727 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
728 p = ZIP(v); /* grab values in bit order */
729 h = -1; /* no tables yet--level -1 */
730 w = l[-1] = 0; /* no bits decoded yet */
731 ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */
732 q = (struct Ziphuft *)NULL; /* ditto */
733 z = 0; /* ditto */
735 /* go through the bit lengths (k already is bits in shortest code) */
736 for (; k <= g; k++)
738 a = ZIP(c)[k];
739 while (a--)
741 /* here i is the Huffman code of length k bits for value *p */
742 /* make tables up to required level */
743 while (k > w + l[h])
745 w += l[h++]; /* add bits already decoded */
747 /* compute minimum size table less than or equal to *m bits */
748 z = (z = g - w) > (cab_ULONG)*m ? *m : z; /* upper limit */
749 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
750 { /* too few codes for k-w bit table */
751 f -= a + 1; /* deduct codes from patterns left */
752 xp = ZIP(c) + k;
753 while (++j < z) /* try smaller tables up to z bits */
755 if ((f <<= 1) <= *++xp)
756 break; /* enough codes to use up j bits */
757 f -= *xp; /* else deduct codes from patterns */
760 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
761 j = el - w; /* make EOB code end at table */
762 z = 1 << j; /* table entries for j-bit table */
763 l[h] = j; /* set table size in stack */
765 /* allocate and link in new table */
766 if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
768 if(h)
769 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
770 return 3; /* not enough memory */
772 *t = q + 1; /* link to list for Ziphuft_free() */
773 *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
774 ZIP(u)[h] = ++q; /* table starts after link */
776 /* connect to last table, if there is one */
777 if (h)
779 ZIP(x)[h] = i; /* save pattern for backing up */
780 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
781 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
782 r.v.t = q; /* pointer to this table */
783 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
784 ZIP(u)[h-1][j] = r; /* connect to last table */
788 /* set up table entry in r */
789 r.b = (cab_UBYTE)(k - w);
790 if (p >= ZIP(v) + n)
791 r.e = 99; /* out of values--invalid code */
792 else if (*p < s)
794 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
795 r.v.n = *p++; /* simple code is just the value */
797 else
799 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
800 r.v.n = d[*p++ - s];
803 /* fill code-like entries with r */
804 f = 1 << (k - w);
805 for (j = i >> w; j < z; j += f)
806 q[j] = r;
808 /* backwards increment the k-bit code i */
809 for (j = 1 << (k - 1); i & j; j >>= 1)
810 i ^= j;
811 i ^= j;
813 /* backup over finished tables */
814 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
815 w -= l[--h]; /* don't need to update q */
819 /* return actual size of base table */
820 *m = l[0];
822 /* Return true (1) if we were given an incomplete table */
823 return y != 0 && g != 1;
826 /*********************************************************
827 * fdi_Zipinflate_codes (internal)
829 cab_LONG fdi_Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td,
830 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
832 register cab_ULONG e; /* table entry flag/number of extra bits */
833 cab_ULONG n, d; /* length and index for copy */
834 cab_ULONG w; /* current window position */
835 struct Ziphuft *t; /* pointer to table entry */
836 cab_ULONG ml, md; /* masks for bl and bd bits */
837 register cab_ULONG b; /* bit buffer */
838 register cab_ULONG k; /* number of bits in bit buffer */
840 /* make local copies of globals */
841 b = ZIP(bb); /* initialize bit buffer */
842 k = ZIP(bk);
843 w = ZIP(window_posn); /* initialize window position */
845 /* inflate the coded data */
846 ml = Zipmask[bl]; /* precompute masks for speed */
847 md = Zipmask[bd];
849 for(;;)
851 ZIPNEEDBITS((cab_ULONG)bl)
852 if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16)
855 if (e == 99)
856 return 1;
857 ZIPDUMPBITS(t->b)
858 e -= 16;
859 ZIPNEEDBITS(e)
860 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
861 ZIPDUMPBITS(t->b)
862 if (e == 16) /* then it's a literal */
863 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
864 else /* it's an EOB or a length */
866 /* exit if end of block */
867 if(e == 15)
868 break;
870 /* get length of block to copy */
871 ZIPNEEDBITS(e)
872 n = t->v.n + ((cab_ULONG)b & Zipmask[e]);
873 ZIPDUMPBITS(e);
875 /* decode distance of block to copy */
876 ZIPNEEDBITS((cab_ULONG)bd)
877 if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16)
878 do {
879 if (e == 99)
880 return 1;
881 ZIPDUMPBITS(t->b)
882 e -= 16;
883 ZIPNEEDBITS(e)
884 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
885 ZIPDUMPBITS(t->b)
886 ZIPNEEDBITS(e)
887 d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]);
888 ZIPDUMPBITS(e)
891 n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
894 CAB(outbuf)[w++] = CAB(outbuf)[d++];
895 } while (--e);
896 } while (n);
900 /* restore the globals from the locals */
901 ZIP(window_posn) = w; /* restore global window pointer */
902 ZIP(bb) = b; /* restore global bit buffer */
903 ZIP(bk) = k;
905 /* done */
906 return 0;
909 /***********************************************************
910 * Zipinflate_stored (internal)
912 cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
913 /* "decompress" an inflated type 0 (stored) block. */
915 cab_ULONG n; /* number of bytes in block */
916 cab_ULONG w; /* current window position */
917 register cab_ULONG b; /* bit buffer */
918 register cab_ULONG k; /* number of bits in bit buffer */
920 /* make local copies of globals */
921 b = ZIP(bb); /* initialize bit buffer */
922 k = ZIP(bk);
923 w = ZIP(window_posn); /* initialize window position */
925 /* go to byte boundary */
926 n = k & 7;
927 ZIPDUMPBITS(n);
929 /* get the length and its complement */
930 ZIPNEEDBITS(16)
931 n = ((cab_ULONG)b & 0xffff);
932 ZIPDUMPBITS(16)
933 ZIPNEEDBITS(16)
934 if (n != (cab_ULONG)((~b) & 0xffff))
935 return 1; /* error in compressed data */
936 ZIPDUMPBITS(16)
938 /* read and output the compressed data */
939 while(n--)
941 ZIPNEEDBITS(8)
942 CAB(outbuf)[w++] = (cab_UBYTE)b;
943 ZIPDUMPBITS(8)
946 /* restore the globals from the locals */
947 ZIP(window_posn) = w; /* restore global window pointer */
948 ZIP(bb) = b; /* restore global bit buffer */
949 ZIP(bk) = k;
950 return 0;
953 /******************************************************
954 * fdi_Zipinflate_fixed (internal)
956 cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
958 struct Ziphuft *fixed_tl;
959 struct Ziphuft *fixed_td;
960 cab_LONG fixed_bl, fixed_bd;
961 cab_LONG i; /* temporary variable */
962 cab_ULONG *l;
964 l = ZIP(ll);
966 /* literal table */
967 for(i = 0; i < 144; i++)
968 l[i] = 8;
969 for(; i < 256; i++)
970 l[i] = 9;
971 for(; i < 280; i++)
972 l[i] = 7;
973 for(; i < 288; i++) /* make a complete, but wrong code set */
974 l[i] = 8;
975 fixed_bl = 7;
976 if((i = fdi_Ziphuft_build(l, 288, 257, (cab_UWORD *) Zipcplens,
977 (cab_UWORD *) Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
978 return i;
980 /* distance table */
981 for(i = 0; i < 30; i++) /* make an incomplete code set */
982 l[i] = 5;
983 fixed_bd = 5;
984 if((i = fdi_Ziphuft_build(l, 30, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
985 &fixed_td, &fixed_bd, decomp_state)) > 1)
987 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
988 return i;
991 /* decompress until an end-of-block code */
992 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
994 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
995 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
996 return i;
999 /**************************************************************
1000 * fdi_Zipinflate_dynamic (internal)
1002 cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1003 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1005 cab_LONG i; /* temporary variables */
1006 cab_ULONG j;
1007 cab_ULONG *ll;
1008 cab_ULONG l; /* last length */
1009 cab_ULONG m; /* mask for bit lengths table */
1010 cab_ULONG n; /* number of lengths to get */
1011 struct Ziphuft *tl; /* literal/length code table */
1012 struct Ziphuft *td; /* distance code table */
1013 cab_LONG bl; /* lookup bits for tl */
1014 cab_LONG bd; /* lookup bits for td */
1015 cab_ULONG nb; /* number of bit length codes */
1016 cab_ULONG nl; /* number of literal/length codes */
1017 cab_ULONG nd; /* number of distance codes */
1018 register cab_ULONG b; /* bit buffer */
1019 register cab_ULONG k; /* number of bits in bit buffer */
1021 /* make local bit buffer */
1022 b = ZIP(bb);
1023 k = ZIP(bk);
1024 ll = ZIP(ll);
1026 /* read in table lengths */
1027 ZIPNEEDBITS(5)
1028 nl = 257 + ((cab_ULONG)b & 0x1f); /* number of literal/length codes */
1029 ZIPDUMPBITS(5)
1030 ZIPNEEDBITS(5)
1031 nd = 1 + ((cab_ULONG)b & 0x1f); /* number of distance codes */
1032 ZIPDUMPBITS(5)
1033 ZIPNEEDBITS(4)
1034 nb = 4 + ((cab_ULONG)b & 0xf); /* number of bit length codes */
1035 ZIPDUMPBITS(4)
1036 if(nl > 288 || nd > 32)
1037 return 1; /* bad lengths */
1039 /* read in bit-length-code lengths */
1040 for(j = 0; j < nb; j++)
1042 ZIPNEEDBITS(3)
1043 ll[Zipborder[j]] = (cab_ULONG)b & 7;
1044 ZIPDUMPBITS(3)
1046 for(; j < 19; j++)
1047 ll[Zipborder[j]] = 0;
1049 /* build decoding table for trees--single level, 7 bit lookup */
1050 bl = 7;
1051 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1053 if(i == 1)
1054 fdi_Ziphuft_free(CAB(hfdi), tl);
1055 return i; /* incomplete code set */
1058 /* read in literal and distance code lengths */
1059 n = nl + nd;
1060 m = Zipmask[bl];
1061 i = l = 0;
1062 while((cab_ULONG)i < n)
1064 ZIPNEEDBITS((cab_ULONG)bl)
1065 j = (td = tl + ((cab_ULONG)b & m))->b;
1066 ZIPDUMPBITS(j)
1067 j = td->v.n;
1068 if (j < 16) /* length of code in bits (0..15) */
1069 ll[i++] = l = j; /* save last length in l */
1070 else if (j == 16) /* repeat last length 3 to 6 times */
1072 ZIPNEEDBITS(2)
1073 j = 3 + ((cab_ULONG)b & 3);
1074 ZIPDUMPBITS(2)
1075 if((cab_ULONG)i + j > n)
1076 return 1;
1077 while (j--)
1078 ll[i++] = l;
1080 else if (j == 17) /* 3 to 10 zero length codes */
1082 ZIPNEEDBITS(3)
1083 j = 3 + ((cab_ULONG)b & 7);
1084 ZIPDUMPBITS(3)
1085 if ((cab_ULONG)i + j > n)
1086 return 1;
1087 while (j--)
1088 ll[i++] = 0;
1089 l = 0;
1091 else /* j == 18: 11 to 138 zero length codes */
1093 ZIPNEEDBITS(7)
1094 j = 11 + ((cab_ULONG)b & 0x7f);
1095 ZIPDUMPBITS(7)
1096 if ((cab_ULONG)i + j > n)
1097 return 1;
1098 while (j--)
1099 ll[i++] = 0;
1100 l = 0;
1104 /* free decoding table for trees */
1105 fdi_Ziphuft_free(CAB(hfdi), tl);
1107 /* restore the global bit buffer */
1108 ZIP(bb) = b;
1109 ZIP(bk) = k;
1111 /* build the decoding tables for literal/length and distance codes */
1112 bl = ZIPLBITS;
1113 if((i = fdi_Ziphuft_build(ll, nl, 257, (cab_UWORD *) Zipcplens, (cab_UWORD *) Zipcplext,
1114 &tl, &bl, decomp_state)) != 0)
1116 if(i == 1)
1117 fdi_Ziphuft_free(CAB(hfdi), tl);
1118 return i; /* incomplete code set */
1120 bd = ZIPDBITS;
1121 fdi_Ziphuft_build(ll + nl, nd, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
1122 &td, &bd, decomp_state);
1124 /* decompress until an end-of-block code */
1125 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1126 return 1;
1128 /* free the decoding tables, return */
1129 fdi_Ziphuft_free(CAB(hfdi), tl);
1130 fdi_Ziphuft_free(CAB(hfdi), td);
1131 return 0;
1134 /*****************************************************
1135 * fdi_Zipinflate_block (internal)
1137 cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1138 { /* decompress an inflated block */
1139 cab_ULONG t; /* block type */
1140 register cab_ULONG b; /* bit buffer */
1141 register cab_ULONG k; /* number of bits in bit buffer */
1143 /* make local bit buffer */
1144 b = ZIP(bb);
1145 k = ZIP(bk);
1147 /* read in last block bit */
1148 ZIPNEEDBITS(1)
1149 *e = (cab_LONG)b & 1;
1150 ZIPDUMPBITS(1)
1152 /* read in block type */
1153 ZIPNEEDBITS(2)
1154 t = (cab_ULONG)b & 3;
1155 ZIPDUMPBITS(2)
1157 /* restore the global bit buffer */
1158 ZIP(bb) = b;
1159 ZIP(bk) = k;
1161 /* inflate that block type */
1162 if(t == 2)
1163 return fdi_Zipinflate_dynamic(decomp_state);
1164 if(t == 0)
1165 return fdi_Zipinflate_stored(decomp_state);
1166 if(t == 1)
1167 return fdi_Zipinflate_fixed(decomp_state);
1168 /* bad block type */
1169 return 2;
1172 /****************************************************
1173 * ZIPfdi_decomp(internal)
1175 int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1177 cab_LONG e; /* last block flag */
1179 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1181 ZIP(inpos) = CAB(inbuf);
1182 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1183 if(outlen > ZIPWSIZE)
1184 return DECR_DATAFORMAT;
1186 /* CK = Chris Kirmse, official Microsoft purloiner */
1187 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1188 return DECR_ILLEGALDATA;
1189 ZIP(inpos) += 2;
1191 do {
1192 if(fdi_Zipinflate_block(&e, decomp_state))
1193 return DECR_ILLEGALDATA;
1194 } while(!e);
1196 /* return success */
1197 return DECR_OK;
1200 /*******************************************************************
1201 * QTMfdi_decomp(internal)
1203 int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1205 cab_UBYTE *inpos = CAB(inbuf);
1206 cab_UBYTE *window = QTM(window);
1207 cab_UBYTE *runsrc, *rundest;
1209 cab_ULONG window_posn = QTM(window_posn);
1210 cab_ULONG window_size = QTM(window_size);
1212 /* used by bitstream macros */
1213 register int bitsleft, bitrun, bitsneed;
1214 register cab_ULONG bitbuf;
1216 /* used by GET_SYMBOL */
1217 cab_ULONG range;
1218 cab_UWORD symf;
1219 int i;
1221 int extra, togo = outlen, match_length = 0, copy_length;
1222 cab_UBYTE selector, sym;
1223 cab_ULONG match_offset = 0;
1225 cab_UWORD H = 0xFFFF, L = 0, C;
1227 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1229 /* read initial value of C */
1230 Q_INIT_BITSTREAM;
1231 Q_READ_BITS(C, 16);
1233 /* apply 2^x-1 mask */
1234 window_posn &= window_size - 1;
1235 /* runs can't straddle the window wraparound */
1236 if ((window_posn + togo) > window_size) {
1237 TRACE("straddled run\n");
1238 return DECR_DATAFORMAT;
1241 while (togo > 0) {
1242 GET_SYMBOL(model7, selector);
1243 switch (selector) {
1244 case 0:
1245 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1246 break;
1247 case 1:
1248 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1249 break;
1250 case 2:
1251 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1252 break;
1253 case 3:
1254 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1255 break;
1257 case 4:
1258 /* selector 4 = fixed length of 3 */
1259 GET_SYMBOL(model4, sym);
1260 Q_READ_BITS(extra, q_extra_bits[sym]);
1261 match_offset = q_position_base[sym] + extra + 1;
1262 match_length = 3;
1263 break;
1265 case 5:
1266 /* selector 5 = fixed length of 4 */
1267 GET_SYMBOL(model5, sym);
1268 Q_READ_BITS(extra, q_extra_bits[sym]);
1269 match_offset = q_position_base[sym] + extra + 1;
1270 match_length = 4;
1271 break;
1273 case 6:
1274 /* selector 6 = variable length */
1275 GET_SYMBOL(model6len, sym);
1276 Q_READ_BITS(extra, q_length_extra[sym]);
1277 match_length = q_length_base[sym] + extra + 5;
1278 GET_SYMBOL(model6pos, sym);
1279 Q_READ_BITS(extra, q_extra_bits[sym]);
1280 match_offset = q_position_base[sym] + extra + 1;
1281 break;
1283 default:
1284 TRACE("Selector is bogus\n");
1285 return DECR_ILLEGALDATA;
1288 /* if this is a match */
1289 if (selector >= 4) {
1290 rundest = window + window_posn;
1291 togo -= match_length;
1293 /* copy any wrapped around source data */
1294 if (window_posn >= match_offset) {
1295 /* no wrap */
1296 runsrc = rundest - match_offset;
1297 } else {
1298 runsrc = rundest + (window_size - match_offset);
1299 copy_length = match_offset - window_posn;
1300 if (copy_length < match_length) {
1301 match_length -= copy_length;
1302 window_posn += copy_length;
1303 while (copy_length-- > 0) *rundest++ = *runsrc++;
1304 runsrc = window;
1307 window_posn += match_length;
1309 /* copy match data - no worries about destination wraps */
1310 while (match_length-- > 0) *rundest++ = *runsrc++;
1312 } /* while (togo > 0) */
1314 if (togo != 0) {
1315 TRACE("Frame overflow, this_run = %d\n", togo);
1316 return DECR_ILLEGALDATA;
1319 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1320 outlen, outlen);
1322 QTM(window_posn) = window_posn;
1323 return DECR_OK;
1326 /************************************************************
1327 * fdi_lzx_read_lens (internal)
1329 int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1330 fdi_decomp_state *decomp_state) {
1331 cab_ULONG i,j, x,y;
1332 int z;
1334 register cab_ULONG bitbuf = lb->bb;
1335 register int bitsleft = lb->bl;
1336 cab_UBYTE *inpos = lb->ip;
1337 cab_UWORD *hufftbl;
1339 for (x = 0; x < 20; x++) {
1340 READ_BITS(y, 4);
1341 LENTABLE(PRETREE)[x] = y;
1343 BUILD_TABLE(PRETREE);
1345 for (x = first; x < last; ) {
1346 READ_HUFFSYM(PRETREE, z);
1347 if (z == 17) {
1348 READ_BITS(y, 4); y += 4;
1349 while (y--) lens[x++] = 0;
1351 else if (z == 18) {
1352 READ_BITS(y, 5); y += 20;
1353 while (y--) lens[x++] = 0;
1355 else if (z == 19) {
1356 READ_BITS(y, 1); y += 4;
1357 READ_HUFFSYM(PRETREE, z);
1358 z = lens[x] - z; if (z < 0) z += 17;
1359 while (y--) lens[x++] = z;
1361 else {
1362 z = lens[x] - z; if (z < 0) z += 17;
1363 lens[x++] = z;
1367 lb->bb = bitbuf;
1368 lb->bl = bitsleft;
1369 lb->ip = inpos;
1370 return 0;
1373 /*******************************************************
1374 * LZXfdi_decomp(internal)
1376 int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1377 cab_UBYTE *inpos = CAB(inbuf);
1378 cab_UBYTE *endinp = inpos + inlen;
1379 cab_UBYTE *window = LZX(window);
1380 cab_UBYTE *runsrc, *rundest;
1381 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1383 cab_ULONG window_posn = LZX(window_posn);
1384 cab_ULONG window_size = LZX(window_size);
1385 cab_ULONG R0 = LZX(R0);
1386 cab_ULONG R1 = LZX(R1);
1387 cab_ULONG R2 = LZX(R2);
1389 register cab_ULONG bitbuf;
1390 register int bitsleft;
1391 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1392 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1394 int togo = outlen, this_run, main_element, aligned_bits;
1395 int match_length, copy_length, length_footer, extra, verbatim_bits;
1397 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1399 INIT_BITSTREAM;
1401 /* read header if necessary */
1402 if (!LZX(header_read)) {
1403 i = j = 0;
1404 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1405 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1406 LZX(header_read) = 1;
1409 /* main decoding loop */
1410 while (togo > 0) {
1411 /* last block finished, new block expected */
1412 if (LZX(block_remaining) == 0) {
1413 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1414 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1415 INIT_BITSTREAM;
1418 READ_BITS(LZX(block_type), 3);
1419 READ_BITS(i, 16);
1420 READ_BITS(j, 8);
1421 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1423 switch (LZX(block_type)) {
1424 case LZX_BLOCKTYPE_ALIGNED:
1425 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1426 BUILD_TABLE(ALIGNED);
1427 /* rest of aligned header is same as verbatim */
1429 case LZX_BLOCKTYPE_VERBATIM:
1430 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1431 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1432 BUILD_TABLE(MAINTREE);
1433 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1435 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1436 BUILD_TABLE(LENGTH);
1437 break;
1439 case LZX_BLOCKTYPE_UNCOMPRESSED:
1440 LZX(intel_started) = 1; /* because we can't assume otherwise */
1441 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1442 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1443 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1444 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1445 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1446 break;
1448 default:
1449 return DECR_ILLEGALDATA;
1453 /* buffer exhaustion check */
1454 if (inpos > endinp) {
1455 /* it's possible to have a file where the next run is less than
1456 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1457 * in building the tables will exhaust the buffer, so we should
1458 * allow for this, but not allow those accidentally read bits to
1459 * be used (so we check that there are at least 16 bits
1460 * remaining - in this boundary case they aren't really part of
1461 * the compressed data)
1463 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1466 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1467 if (this_run > togo) this_run = togo;
1468 togo -= this_run;
1469 LZX(block_remaining) -= this_run;
1471 /* apply 2^x-1 mask */
1472 window_posn &= window_size - 1;
1473 /* runs can't straddle the window wraparound */
1474 if ((window_posn + this_run) > window_size)
1475 return DECR_DATAFORMAT;
1477 switch (LZX(block_type)) {
1479 case LZX_BLOCKTYPE_VERBATIM:
1480 while (this_run > 0) {
1481 READ_HUFFSYM(MAINTREE, main_element);
1483 if (main_element < LZX_NUM_CHARS) {
1484 /* literal: 0 to LZX_NUM_CHARS-1 */
1485 window[window_posn++] = main_element;
1486 this_run--;
1488 else {
1489 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1490 main_element -= LZX_NUM_CHARS;
1492 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1493 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1494 READ_HUFFSYM(LENGTH, length_footer);
1495 match_length += length_footer;
1497 match_length += LZX_MIN_MATCH;
1499 match_offset = main_element >> 3;
1501 if (match_offset > 2) {
1502 /* not repeated offset */
1503 if (match_offset != 3) {
1504 extra = extra_bits[match_offset];
1505 READ_BITS(verbatim_bits, extra);
1506 match_offset = lzx_position_base[match_offset]
1507 - 2 + verbatim_bits;
1509 else {
1510 match_offset = 1;
1513 /* update repeated offset LRU queue */
1514 R2 = R1; R1 = R0; R0 = match_offset;
1516 else if (match_offset == 0) {
1517 match_offset = R0;
1519 else if (match_offset == 1) {
1520 match_offset = R1;
1521 R1 = R0; R0 = match_offset;
1523 else /* match_offset == 2 */ {
1524 match_offset = R2;
1525 R2 = R0; R0 = match_offset;
1528 rundest = window + window_posn;
1529 this_run -= match_length;
1531 /* copy any wrapped around source data */
1532 if (window_posn >= match_offset) {
1533 /* no wrap */
1534 runsrc = rundest - match_offset;
1535 } else {
1536 runsrc = rundest + (window_size - match_offset);
1537 copy_length = match_offset - window_posn;
1538 if (copy_length < match_length) {
1539 match_length -= copy_length;
1540 window_posn += copy_length;
1541 while (copy_length-- > 0) *rundest++ = *runsrc++;
1542 runsrc = window;
1545 window_posn += match_length;
1547 /* copy match data - no worries about destination wraps */
1548 while (match_length-- > 0) *rundest++ = *runsrc++;
1551 break;
1553 case LZX_BLOCKTYPE_ALIGNED:
1554 while (this_run > 0) {
1555 READ_HUFFSYM(MAINTREE, main_element);
1557 if (main_element < LZX_NUM_CHARS) {
1558 /* literal: 0 to LZX_NUM_CHARS-1 */
1559 window[window_posn++] = main_element;
1560 this_run--;
1562 else {
1563 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1564 main_element -= LZX_NUM_CHARS;
1566 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1567 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1568 READ_HUFFSYM(LENGTH, length_footer);
1569 match_length += length_footer;
1571 match_length += LZX_MIN_MATCH;
1573 match_offset = main_element >> 3;
1575 if (match_offset > 2) {
1576 /* not repeated offset */
1577 extra = extra_bits[match_offset];
1578 match_offset = lzx_position_base[match_offset] - 2;
1579 if (extra > 3) {
1580 /* verbatim and aligned bits */
1581 extra -= 3;
1582 READ_BITS(verbatim_bits, extra);
1583 match_offset += (verbatim_bits << 3);
1584 READ_HUFFSYM(ALIGNED, aligned_bits);
1585 match_offset += aligned_bits;
1587 else if (extra == 3) {
1588 /* aligned bits only */
1589 READ_HUFFSYM(ALIGNED, aligned_bits);
1590 match_offset += aligned_bits;
1592 else if (extra > 0) { /* extra==1, extra==2 */
1593 /* verbatim bits only */
1594 READ_BITS(verbatim_bits, extra);
1595 match_offset += verbatim_bits;
1597 else /* extra == 0 */ {
1598 /* ??? */
1599 match_offset = 1;
1602 /* update repeated offset LRU queue */
1603 R2 = R1; R1 = R0; R0 = match_offset;
1605 else if (match_offset == 0) {
1606 match_offset = R0;
1608 else if (match_offset == 1) {
1609 match_offset = R1;
1610 R1 = R0; R0 = match_offset;
1612 else /* match_offset == 2 */ {
1613 match_offset = R2;
1614 R2 = R0; R0 = match_offset;
1617 rundest = window + window_posn;
1618 this_run -= match_length;
1620 /* copy any wrapped around source data */
1621 if (window_posn >= match_offset) {
1622 /* no wrap */
1623 runsrc = rundest - match_offset;
1624 } else {
1625 runsrc = rundest + (window_size - match_offset);
1626 copy_length = match_offset - window_posn;
1627 if (copy_length < match_length) {
1628 match_length -= copy_length;
1629 window_posn += copy_length;
1630 while (copy_length-- > 0) *rundest++ = *runsrc++;
1631 runsrc = window;
1634 window_posn += match_length;
1636 /* copy match data - no worries about destination wraps */
1637 while (match_length-- > 0) *rundest++ = *runsrc++;
1640 break;
1642 case LZX_BLOCKTYPE_UNCOMPRESSED:
1643 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1644 memcpy(window + window_posn, inpos, (size_t) this_run);
1645 inpos += this_run; window_posn += this_run;
1646 break;
1648 default:
1649 return DECR_ILLEGALDATA; /* might as well */
1655 if (togo != 0) return DECR_ILLEGALDATA;
1656 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1657 outlen, (size_t) outlen);
1659 LZX(window_posn) = window_posn;
1660 LZX(R0) = R0;
1661 LZX(R1) = R1;
1662 LZX(R2) = R2;
1664 /* intel E8 decoding */
1665 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1666 if (outlen <= 6 || !LZX(intel_started)) {
1667 LZX(intel_curpos) += outlen;
1669 else {
1670 cab_UBYTE *data = CAB(outbuf);
1671 cab_UBYTE *dataend = data + outlen - 10;
1672 cab_LONG curpos = LZX(intel_curpos);
1673 cab_LONG filesize = LZX(intel_filesize);
1674 cab_LONG abs_off, rel_off;
1676 LZX(intel_curpos) = curpos + outlen;
1678 while (data < dataend) {
1679 if (*data++ != 0xE8) { curpos++; continue; }
1680 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1681 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1682 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1683 data[0] = (cab_UBYTE) rel_off;
1684 data[1] = (cab_UBYTE) (rel_off >> 8);
1685 data[2] = (cab_UBYTE) (rel_off >> 16);
1686 data[3] = (cab_UBYTE) (rel_off >> 24);
1688 data += 4;
1689 curpos += 5;
1693 return DECR_OK;
1696 /**********************************************************
1697 * fdi_decomp (internal)
1699 int fdi_decomp(struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state)
1701 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
1702 cab_UBYTE buf[cfdata_SIZEOF], *data;
1703 cab_UWORD inlen, len, outlen, cando;
1704 cab_ULONG cksum;
1705 cab_LONG err;
1707 TRACE("(fi == ^%p, savemode == %d)\n", fi, savemode);
1709 while (bytes > 0) {
1710 /* cando = the max number of bytes we can do */
1711 cando = CAB(outlen);
1712 if (cando > bytes) cando = bytes;
1714 /* if cando != 0 */
1715 if (cando && savemode)
1716 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
1718 CAB(outpos) += cando;
1719 CAB(outlen) -= cando;
1720 bytes -= cando; if (!bytes) break;
1722 /* we only get here if we emptied the output buffer */
1724 /* read data header + data */
1725 inlen = outlen = 0;
1726 while (outlen == 0) {
1727 /* read the block header, skip the reserved part */
1728 if (PFDI_READ(CAB(hfdi), CAB(cabhf), buf, cfdata_SIZEOF) != cfdata_SIZEOF)
1729 return DECR_INPUT;
1731 if (PFDI_SEEK(CAB(hfdi), CAB(cabhf), CAB(block_resv), SEEK_CUR) == -1)
1732 return DECR_INPUT;
1734 /* we shouldn't get blocks over CAB_INPUTMAX in size */
1735 data = CAB(inbuf) + inlen;
1736 len = EndGetI16(buf+cfdata_CompressedSize);
1737 inlen += len;
1738 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
1739 if (PFDI_READ(CAB(hfdi), CAB(cabhf), data, len) != len)
1740 return DECR_INPUT;
1742 /* clear two bytes after read-in data */
1743 data[len+1] = data[len+2] = 0;
1745 /* perform checksum test on the block (if one is stored) */
1746 cksum = EndGetI32(buf+cfdata_CheckSum);
1747 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
1748 return DECR_CHECKSUM; /* checksum is wrong */
1750 /* outlen=0 means this block was part of a split block */
1751 outlen = EndGetI16(buf+cfdata_UncompressedSize);
1752 if (outlen == 0) {
1754 cabinet_close(cab);
1755 cab = CAB(current)->cab[++CAB(split)];
1756 if (!cabinet_open(cab)) return DECR_INPUT;
1757 cabinet_seek(cab, CAB(current)->offset[CAB(split)]); */
1758 FIXME("split block... ack! fix this.\n");
1759 return DECR_INPUT;
1763 /* decompress block */
1764 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
1765 return err;
1766 CAB(outlen) = outlen;
1767 CAB(outpos) = CAB(outbuf);
1770 return DECR_OK;
1773 /***********************************************************************
1774 * FDICopy (CABINET.22)
1776 BOOL __cdecl FDICopy(
1777 HFDI hfdi,
1778 char *pszCabinet,
1779 char *pszCabPath,
1780 int flags,
1781 PFNFDINOTIFY pfnfdin,
1782 PFNFDIDECRYPT pfnfdid,
1783 void *pvUser)
1785 FDICABINETINFO fdici;
1786 FDINOTIFICATION fdin;
1787 MORE_ISCAB_INFO mii;
1788 int cabhf, filehf;
1789 int i, idx;
1790 char fullpath[MAX_PATH];
1791 size_t pathlen, filenamelen;
1792 char emptystring = '\0';
1793 cab_UBYTE buf[64], buf2[256] /* for modification by call back fn */ ;
1794 BOOL initialcab = TRUE;
1795 struct fdi_folder *fol = NULL, *linkfol = NULL, *firstfol = NULL;
1796 struct fdi_file *file = NULL, *linkfile = NULL, *firstfile = NULL;
1798 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, \
1799 pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
1800 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
1802 if (!REALLY_IS_FDI(hfdi)) {
1803 SetLastError(ERROR_INVALID_HANDLE);
1804 return FALSE;
1807 while (TRUE) { /* this loop executes one per. cabinet */
1808 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
1809 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
1811 /* slight overestimation here to save CPU cycles in the developer's brain */
1812 if ((pathlen + filenamelen + 3) > MAX_PATH) {
1813 ERR("MAX_PATH exceeded.\n");
1814 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
1815 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
1816 PFDI_INT(hfdi)->perf->fError = TRUE;
1817 SetLastError(ERROR_FILE_NOT_FOUND);
1818 return FALSE;
1821 /* paste the path and filename together */
1822 idx = 0;
1823 if (pathlen) {
1824 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
1825 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
1827 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
1828 fullpath[idx] = '\0';
1830 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
1832 /* get a handle to the cabfile */
1833 cabhf = PFDI_OPEN(hfdi, fullpath, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
1834 if (cabhf == -1) {
1835 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
1836 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
1837 PFDI_INT(hfdi)->perf->fError = TRUE;
1838 SetLastError(ERROR_FILE_NOT_FOUND);
1839 return FALSE;
1842 /* check if it's really a cabfile. Note that this doesn't implement the bug */
1843 if (!FDI_read_entries(hfdi, cabhf, &fdici, &mii)) {
1844 ERR("FDIIsCabinet failed.\n");
1845 PFDI_CLOSE(hfdi, cabhf);
1846 return FALSE;
1849 /* cabinet notification */
1850 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1851 fdin.setID = fdici.setID;
1852 fdin.iCabinet = fdici.iCabinet;
1853 fdin.pv = pvUser;
1854 fdin.psz1 = (mii.nextname) ? mii.nextname : &emptystring;
1855 fdin.psz2 = (mii.nextinfo) ? mii.nextinfo : &emptystring;
1856 fdin.psz3 = pszCabPath;
1858 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
1859 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
1860 PFDI_INT(hfdi)->perf->erfType = 0;
1861 PFDI_INT(hfdi)->perf->fError = TRUE;
1862 goto bail_and_fail;
1865 /* read folders */
1866 for (i = 0; i < fdici.cFolders; i++) {
1867 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
1868 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
1869 PFDI_INT(hfdi)->perf->erfType = 0;
1870 PFDI_INT(hfdi)->perf->fError = TRUE;
1871 goto bail_and_fail;
1874 if (mii.folder_resv > 0)
1875 PFDI_SEEK(hfdi, cabhf, mii.folder_resv, SEEK_CUR);
1877 fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
1878 if (!fol) {
1879 ERR("out of memory!\n");
1880 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
1881 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
1882 PFDI_INT(hfdi)->perf->fError = TRUE;
1883 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1884 goto bail_and_fail;
1886 ZeroMemory(fol, sizeof(struct fdi_folder));
1887 if (!firstfol) firstfol = fol;
1889 fol->offset[0] = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
1890 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
1891 fol->comp_type = EndGetI16(buf+cffold_CompType);
1893 if (linkfol)
1894 linkfol->next = fol;
1895 linkfol = fol;
1898 /* read files */
1899 for (i = 0; i < fdici.cFiles; i++) {
1900 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
1901 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
1902 PFDI_INT(hfdi)->perf->erfType = 0;
1903 PFDI_INT(hfdi)->perf->fError = TRUE;
1904 goto bail_and_fail;
1907 file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
1908 if (!file) {
1909 ERR("out of memory!\n");
1910 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
1911 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
1912 PFDI_INT(hfdi)->perf->fError = TRUE;
1913 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1914 goto bail_and_fail;
1916 ZeroMemory(file, sizeof(struct fdi_file));
1917 if (!firstfile) firstfile = file;
1919 file->length = EndGetI32(buf+cffile_UncompressedSize);
1920 file->offset = EndGetI32(buf+cffile_FolderOffset);
1921 file->index = EndGetI16(buf+cffile_FolderIndex);
1922 file->time = EndGetI16(buf+cffile_Time);
1923 file->date = EndGetI16(buf+cffile_Date);
1924 file->attribs = EndGetI16(buf+cffile_Attribs);
1925 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
1927 if (!file->filename) {
1928 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
1929 PFDI_INT(hfdi)->perf->erfType = 0;
1930 PFDI_INT(hfdi)->perf->fError = TRUE;
1931 goto bail_and_fail;
1934 if (linkfile)
1935 linkfile->next = file;
1936 linkfile = file;
1939 for (file = firstfile; (file); file = file->next) {
1940 /* partial file notification (do it just once for the first cabinet) */
1941 if (initialcab && ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV)) {
1942 /* OK, more MS bugs to simulate here, I think. I don't have a huge spanning
1943 * cabinet to test this theory on ATM, but here's the deal. The SDK says that we
1944 * are supposed to notify the user of the filename and "disk name" (info) of
1945 * the cabinet where the spanning file /started/. That would certainly be convenient
1946 * for the consumer, who could decide to abort everything and try to start over with
1947 * that cabinet so as not to create a front-truncated output file. Note that this
1948 * task would be a horrible bitch from the implementor's (wine's) perspective: the
1949 * information is associated nowhere with the file header and is not to be found in
1950 * the cabinet header. So we would have to open the previous cabinet, and check
1951 * if it contains a single spanning file that's continued from yet another prior cabinet,
1952 * and so-on, until we find the beginning. Note that cabextract.c has code to do exactly
1953 * this. Luckily, MS clearly didn't implement this logic, so we don't have to either.
1954 * Watching the callbacks (and debugmsg +file) clearly shows that they don't open
1955 * the preceeding cabinet -- and therefore, I deduce, there is NO WAY they could
1956 * have implemented what's in the spec. Instead, they are obviously just returning
1957 * the previous cabinet and it's info from the header of this cabinet. So we shall
1958 * do the same. Of course, I could be missing something...
1960 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1961 fdin.pv = pvUser;
1962 fdin.psz1 = (char *)file->filename;
1963 fdin.psz2 = (mii.prevname) ? mii.prevname : &emptystring;
1964 fdin.psz3 = (mii.previnfo) ? mii.previnfo : &emptystring;
1966 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
1967 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
1968 PFDI_INT(hfdi)->perf->erfType = 0;
1969 PFDI_INT(hfdi)->perf->fError = TRUE;
1970 goto bail_and_fail;
1972 /* I don't think we are supposed to decompress partial files */
1973 file->oppressed = TRUE;
1975 if (file->oppressed) {
1976 filehf = 0;
1977 } else {
1978 /* fdintCOPY_FILE notification (TODO: skip for spanning cab's we already should have hf) */
1979 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1980 fdin.pv = pvUser;
1981 fdin.psz1 = (char *)file->filename;
1982 fdin.cb = file->length;
1983 fdin.date = file->date;
1984 fdin.time = file->time;
1985 fdin.attribs = file->attribs;
1986 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
1987 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
1988 PFDI_INT(hfdi)->perf->erfType = 0;
1989 PFDI_INT(hfdi)->perf->fError = TRUE;
1990 goto bail_and_fail;
1994 if (filehf) {
1995 cab_UWORD comptype = fol->comp_type;
1996 int ct1 = comptype & cffoldCOMPTYPE_MASK;
1997 fdi_decomp_state _decomp_state;
1998 fdi_decomp_state *decomp_state = &_decomp_state;
1999 int err = 0;
2001 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2003 /* set up decomp_state */
2004 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2005 CAB(hfdi) = hfdi;
2006 CAB(filehf) = filehf;
2007 CAB(cabhf) = cabhf;
2008 CAB(current) = file->folder;
2009 CAB(block_resv) = mii.block_resv;
2011 /* set up the appropriate decompressor */
2012 switch (ct1) {
2013 case cffoldCOMPTYPE_NONE:
2014 CAB(decompress) = NONEfdi_decomp;
2015 break;
2016 case cffoldCOMPTYPE_MSZIP:
2017 CAB(decompress) = ZIPfdi_decomp;
2018 break;
2019 case cffoldCOMPTYPE_QUANTUM:
2020 CAB(decompress) = QTMfdi_decomp;
2021 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2022 break;
2023 case cffoldCOMPTYPE_LZX:
2024 CAB(decompress) = LZXfdi_decomp;
2025 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2026 break;
2027 default:
2028 err = DECR_DATAFORMAT;
2031 switch (err) {
2032 case DECR_OK:
2033 break;
2034 case DECR_NOMEMORY:
2035 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2036 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2037 PFDI_INT(hfdi)->perf->fError = TRUE;
2038 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2039 goto bail_and_fail;
2040 default:
2041 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2042 PFDI_INT(hfdi)->perf->erfOper = 0;
2043 PFDI_INT(hfdi)->perf->fError = TRUE;
2044 goto bail_and_fail;
2047 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset[0], SEEK_SET);
2048 CAB(offset) = 0;
2049 CAB(outlen) = 0;
2050 CAB(split) = 0;
2052 if (file->offset > CAB(offset)) {
2053 /* decode bytes and send them to /dev/null */
2054 switch ((err = fdi_decomp(file, 0, decomp_state))) {
2055 case DECR_OK:
2056 break;
2057 case DECR_NOMEMORY:
2058 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2059 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2060 PFDI_INT(hfdi)->perf->fError = TRUE;
2061 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2062 goto bail_and_fail;
2063 default:
2064 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2065 PFDI_INT(hfdi)->perf->erfOper = 0;
2066 PFDI_INT(hfdi)->perf->fError = TRUE;
2067 goto bail_and_fail;
2069 CAB(offset) = file->offset;
2072 /* now do the actual decompression */
2073 err = fdi_decomp(file, 1, decomp_state);
2074 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2076 switch (err) {
2077 case DECR_OK:
2078 break;
2079 case DECR_NOMEMORY:
2080 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2081 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2082 PFDI_INT(hfdi)->perf->fError = TRUE;
2083 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2084 goto bail_and_fail;
2085 default:
2086 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2087 PFDI_INT(hfdi)->perf->erfOper = 0;
2088 PFDI_INT(hfdi)->perf->fError = TRUE;
2089 goto bail_and_fail;
2092 /* FIXME: don't do it if we are continuing the file in another cab */
2093 /* fdintCLOSE_FILE_INFO notification */
2094 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2095 fdin.pv = pvUser;
2096 fdin.psz1 = (char *)file->filename;
2097 fdin.hf = filehf;
2098 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE;
2099 fdin.date = file->date;
2100 fdin.time = file->time;
2101 fdin.attribs = file->attribs;
2102 err = ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2103 if (err == FALSE || err == -1) {
2105 * SDK states that even though they indicated failure,
2106 * we are not supposed to try and close the file, so we
2107 * just treat this like all the others
2109 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2110 PFDI_INT(hfdi)->perf->erfType = 0;
2111 PFDI_INT(hfdi)->perf->fError = TRUE;
2112 goto bail_and_fail;
2117 while (firstfol) {
2118 fol = firstfol;
2119 firstfol = firstfol->next;
2120 PFDI_FREE(hfdi, fol);
2122 while (firstfile) {
2123 file = firstfile;
2124 firstfile = firstfile->next;
2125 PFDI_FREE(hfdi, file);
2128 /* free the storage remembered by mii */
2129 if (mii.nextname) PFDI_FREE(hfdi, mii.nextname);
2130 if (mii.nextinfo) PFDI_FREE(hfdi, mii.nextinfo);
2131 if (mii.prevname) PFDI_FREE(hfdi, mii.prevname);
2132 if (mii.previnfo) PFDI_FREE(hfdi, mii.previnfo);
2134 PFDI_CLOSE(hfdi, cabhf);
2135 /* TODO: if (:?) */ return TRUE; /* else { ...; initialcab=FALSE; continue; } */
2137 bail_and_fail: /* here we free ram before error returns */
2139 while (firstfol) {
2140 fol = firstfol;
2141 firstfol = firstfol->next;
2142 PFDI_FREE(hfdi, fol);
2144 while (firstfile) {
2145 file = firstfile;
2146 firstfile = firstfile->next;
2147 PFDI_FREE(hfdi, file);
2150 /* free the storage remembered by mii */
2151 if (mii.nextname) PFDI_FREE(hfdi, mii.nextname);
2152 if (mii.nextinfo) PFDI_FREE(hfdi, mii.nextinfo);
2153 if (mii.prevname) PFDI_FREE(hfdi, mii.prevname);
2154 if (mii.previnfo) PFDI_FREE(hfdi, mii.previnfo);
2156 PFDI_CLOSE(hfdi, cabhf);
2157 return FALSE;
2161 /***********************************************************************
2162 * FDIDestroy (CABINET.23)
2164 BOOL __cdecl FDIDestroy(HFDI hfdi)
2166 TRACE("(hfdi == ^%p)\n", hfdi);
2167 if (REALLY_IS_FDI(hfdi)) {
2168 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2169 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2170 return TRUE;
2171 } else {
2172 SetLastError(ERROR_INVALID_HANDLE);
2173 return FALSE;
2177 /***********************************************************************
2178 * FDITruncateCabinet (CABINET.24)
2180 BOOL __cdecl FDITruncateCabinet(
2181 HFDI hfdi,
2182 char *pszCabinetName,
2183 USHORT iFolderToDelete)
2185 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2186 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2188 if (!REALLY_IS_FDI(hfdi)) {
2189 SetLastError(ERROR_INVALID_HANDLE);
2190 return FALSE;
2193 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2194 return FALSE;