Added some stubs.
[wine/wine64.git] / dlls / cabinet / fdi.c
blobf2673014fea0c84f686d1185542248e488bcc7a1
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 struct fdi_folder *firstfol;
97 struct fdi_file *firstfile;
98 struct fdi_cds_fwd *next;
99 } fdi_decomp_state;
102 * this structure fills the gaps between what is available in a PFDICABINETINFO
103 * vs what is needed by FDICopy. Memory allocated for these becomes the responsibility
104 * of the caller to free. Yes, I am aware that this is totally, utterly inelegant.
106 typedef struct {
107 char *prevname, *previnfo;
108 char *nextname, *nextinfo;
109 int folder_resv, header_resv;
110 cab_UBYTE block_resv;
111 } MORE_ISCAB_INFO, *PMORE_ISCAB_INFO;
113 /***********************************************************************
114 * FDICreate (CABINET.20)
116 HFDI __cdecl FDICreate(
117 PFNALLOC pfnalloc,
118 PFNFREE pfnfree,
119 PFNOPEN pfnopen,
120 PFNREAD pfnread,
121 PFNWRITE pfnwrite,
122 PFNCLOSE pfnclose,
123 PFNSEEK pfnseek,
124 int cpuType,
125 PERF perf)
127 HFDI rv;
129 TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, \
130 pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
131 pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
132 cpuType, perf);
134 /* PONDERME: Certainly, we cannot tolerate a missing pfnalloc, as we call it just below.
135 pfnfree is tested as well, for symmetry. As for the rest, should we test these
136 too? In a vacuum, I would say yes... but does Windows care? If not, then, I guess,
137 neither do we.... */
138 if ((!pfnalloc) || (!pfnfree)) {
139 perf->erfOper = FDIERROR_NONE;
140 perf->erfType = ERROR_BAD_ARGUMENTS;
141 perf->fError = TRUE;
143 SetLastError(ERROR_BAD_ARGUMENTS);
144 return NULL;
147 if (!((rv = ((HFDI) (*pfnalloc)(sizeof(FDI_Int)))))) {
148 perf->erfOper = FDIERROR_ALLOC_FAIL;
149 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
150 perf->fError = TRUE;
152 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
153 return NULL;
156 PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
157 PFDI_INT(rv)->pfnalloc = pfnalloc;
158 PFDI_INT(rv)->pfnfree = pfnfree;
159 PFDI_INT(rv)->pfnopen = pfnopen;
160 PFDI_INT(rv)->pfnread = pfnread;
161 PFDI_INT(rv)->pfnwrite = pfnwrite;
162 PFDI_INT(rv)->pfnclose = pfnclose;
163 PFDI_INT(rv)->pfnseek = pfnseek;
164 /* no-brainer: we ignore the cpu type; this is only used
165 for the 16-bit versions in Windows anyhow... */
166 PFDI_INT(rv)->perf = perf;
168 return rv;
171 /*******************************************************************
172 * FDI_getoffset (internal)
174 * returns the file pointer position of a cab
176 long FDI_getoffset(HFDI hfdi, INT_PTR hf)
178 return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
181 /**********************************************************************
182 * FDI_realloc (internal)
184 * we can't use _msize; the user might not be using malloc, so we require
185 * an explicit specification of the previous size. utterly inefficient.
187 void *FDI_realloc(HFDI hfdi, void *mem, size_t prevsize, size_t newsize)
189 void *rslt = NULL;
190 char *irslt, *imem;
191 size_t copysize = (prevsize < newsize) ? prevsize : newsize;
192 if (prevsize == newsize) return mem;
193 rslt = PFDI_ALLOC(hfdi, newsize);
194 if (rslt)
195 for (irslt = (char *)rslt, imem = (char *)mem; (copysize); copysize--)
196 *irslt++ = *imem++;
197 PFDI_FREE(hfdi, mem);
198 return rslt;
201 /**********************************************************************
202 * FDI_read_string (internal)
204 * allocate and read an aribitrarily long string from the cabinet
206 char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
208 size_t len=256,
209 oldlen = 0,
210 base = FDI_getoffset(hfdi, hf),
211 maxlen = cabsize - base;
212 BOOL ok = FALSE;
213 int i;
214 cab_UBYTE *buf = NULL;
216 TRACE("(hfdi == ^%p, hf == %d)\n", hfdi, hf);
218 do {
219 if (len > maxlen) len = maxlen;
220 if (!(buf = FDI_realloc(hfdi, buf, oldlen, len))) break;
221 oldlen = len;
222 if (!PFDI_READ(hfdi, hf, buf, len)) break;
224 /* search for a null terminator in what we've just read */
225 for (i=0; i < len; i++) {
226 if (!buf[i]) {ok=TRUE; break;}
229 if (!ok) {
230 if (len == maxlen) {
231 ERR("WARNING: cabinet is truncated\n");
232 break;
234 len += 256;
235 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
237 } while (!ok);
239 if (!ok) {
240 if (buf)
241 PFDI_FREE(hfdi, buf);
242 else
243 ERR("out of memory!\n");
244 return NULL;
247 /* otherwise, set the stream to just after the string and return */
248 PFDI_SEEK(hfdi, hf, base + ((cab_off_t) strlen((char *) buf)) + 1, SEEK_SET);
250 return (char *) buf;
253 /******************************************************************
254 * FDI_read_entries (internal)
256 * process the cabinet header in the style of FDIIsCabinet, but
257 * without the sanity checks (and bug)
259 * if pmii is non-null, some info not expressed in FDICABINETINFO struct
260 * will be stored there... responsibility to free the enclosed stuff is
261 * delegated to the caller in this case.
263 BOOL FDI_read_entries(
264 HFDI hfdi,
265 INT_PTR hf,
266 PFDICABINETINFO pfdici,
267 PMORE_ISCAB_INFO pmii)
269 int num_folders, num_files, header_resv, folder_resv = 0;
270 LONG base_offset, cabsize;
271 USHORT setid, cabidx, flags;
272 cab_UBYTE buf[64], block_resv;
273 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
275 TRACE("(hfdi == ^%p, hf == %d, pfdici == ^%p)\n", hfdi, hf, pfdici);
277 if (pmii) ZeroMemory(pmii, sizeof(MORE_ISCAB_INFO));
279 /* get basic offset & size info */
280 base_offset = FDI_getoffset(hfdi, hf);
282 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
283 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
284 PFDI_INT(hfdi)->perf->erfType = 0;
285 PFDI_INT(hfdi)->perf->fError = TRUE;
286 return FALSE;
289 cabsize = FDI_getoffset(hfdi, hf);
291 if ((cabsize == -1) || (base_offset == -1) ||
292 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
293 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
294 PFDI_INT(hfdi)->perf->erfType = 0;
295 PFDI_INT(hfdi)->perf->fError = TRUE;
296 return FALSE;
299 /* read in the CFHEADER */
300 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
301 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
302 PFDI_INT(hfdi)->perf->erfType = 0;
303 PFDI_INT(hfdi)->perf->fError = TRUE;
304 return FALSE;
307 /* check basic MSCF signature */
308 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
309 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
310 PFDI_INT(hfdi)->perf->erfType = 0;
311 PFDI_INT(hfdi)->perf->fError = TRUE;
312 return FALSE;
315 /* get the number of folders */
316 num_folders = EndGetI16(buf+cfhead_NumFolders);
317 if (num_folders == 0) {
318 /* PONDERME: is this really invalid? */
319 WARN("weird cabinet detect failure: no folders in cabinet\n");
320 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
321 PFDI_INT(hfdi)->perf->erfType = 0;
322 PFDI_INT(hfdi)->perf->fError = TRUE;
323 return FALSE;
326 /* get the number of files */
327 num_files = EndGetI16(buf+cfhead_NumFiles);
328 if (num_files == 0) {
329 /* PONDERME: is this really invalid? */
330 WARN("weird cabinet detect failure: no files in cabinet\n");
331 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
332 PFDI_INT(hfdi)->perf->erfType = 0;
333 PFDI_INT(hfdi)->perf->fError = TRUE;
334 return FALSE;
337 /* setid */
338 setid = EndGetI16(buf+cfhead_SetID);
340 /* cabinet (set) index */
341 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
343 /* check the header revision */
344 if ((buf[cfhead_MajorVersion] > 1) ||
345 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
347 WARN("cabinet format version > 1.3\n");
348 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
349 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
350 PFDI_INT(hfdi)->perf->fError = TRUE;
351 return FALSE;
354 /* pull the flags out */
355 flags = EndGetI16(buf+cfhead_Flags);
357 /* read the reserved-sizes part of header, if present */
358 if (flags & cfheadRESERVE_PRESENT) {
359 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
360 ERR("bunk reserve-sizes?\n");
361 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
362 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
363 PFDI_INT(hfdi)->perf->fError = TRUE;
364 return FALSE;
367 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
368 if (pmii) pmii->header_resv = header_resv;
369 folder_resv = buf[cfheadext_FolderReserved];
370 if (pmii) pmii->folder_resv = folder_resv;
371 block_resv = buf[cfheadext_DataReserved];
372 if (pmii) pmii->block_resv = block_resv;
374 if (header_resv > 60000) {
375 WARN("WARNING; header reserved space > 60000\n");
378 /* skip the reserved header */
379 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
380 ERR("seek failure: header_resv\n");
381 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
382 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
383 PFDI_INT(hfdi)->perf->fError = TRUE;
384 return FALSE;
388 if (flags & cfheadPREV_CABINET) {
389 prevname = FDI_read_string(hfdi, hf, cabsize);
390 if (!prevname) {
391 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
392 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
393 PFDI_INT(hfdi)->perf->fError = TRUE;
394 return FALSE;
395 } else
396 if (pmii)
397 pmii->prevname = prevname;
398 else
399 PFDI_FREE(hfdi, prevname);
400 previnfo = FDI_read_string(hfdi, hf, cabsize);
401 if (previnfo) {
402 if (pmii)
403 pmii->previnfo = previnfo;
404 else
405 PFDI_FREE(hfdi, previnfo);
409 if (flags & cfheadNEXT_CABINET) {
410 nextname = FDI_read_string(hfdi, hf, cabsize);
411 if (!nextname) {
412 if ((flags & cfheadPREV_CABINET) && pmii) {
413 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
414 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
416 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
417 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
418 PFDI_INT(hfdi)->perf->fError = TRUE;
419 return FALSE;
420 } else
421 if (pmii)
422 pmii->nextname = nextname;
423 else
424 PFDI_FREE(hfdi, nextname);
425 nextinfo = FDI_read_string(hfdi, hf, cabsize);
426 if (nextinfo) {
427 if (pmii)
428 pmii->nextinfo = nextinfo;
429 else
430 PFDI_FREE(hfdi, nextinfo);
434 /* we could process the whole cabinet searching for problems;
435 instead lets stop here. Now let's fill out the paperwork */
436 pfdici->cbCabinet = cabsize;
437 pfdici->cFolders = num_folders;
438 pfdici->cFiles = num_files;
439 pfdici->setID = setid;
440 pfdici->iCabinet = cabidx;
441 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
442 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
443 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
444 return TRUE;
447 /***********************************************************************
448 * FDIIsCabinet (CABINET.21)
450 BOOL __cdecl FDIIsCabinet(
451 HFDI hfdi,
452 INT_PTR hf,
453 PFDICABINETINFO pfdici)
455 BOOL rv;
457 TRACE("(hfdi == ^%p, hf == ^%d, pfdici == ^%p)\n", hfdi, hf, pfdici);
459 if (!REALLY_IS_FDI(hfdi)) {
460 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
461 SetLastError(ERROR_INVALID_HANDLE);
462 return FALSE;
465 if (!hf) {
466 ERR("(!hf)!\n");
467 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
468 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
469 PFDI_INT(hfdi)->perf->fError = TRUE;
470 SetLastError(ERROR_INVALID_HANDLE);
471 return FALSE;
474 if (!pfdici) {
475 ERR("(!pfdici)!\n");
476 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
477 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
478 PFDI_INT(hfdi)->perf->fError = TRUE;
479 SetLastError(ERROR_BAD_ARGUMENTS);
480 return FALSE;
482 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
484 if (rv)
485 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
487 return rv;
490 /* FIXME: eliminate global variables */
491 static cab_UBYTE q_length_base[27], q_length_extra[27], q_extra_bits[42];
492 static cab_ULONG q_position_base[42];
494 /******************************************************************
495 * QTMfdi_initmodel (internal)
497 * Initialise a model which decodes symbols from [s] to [s]+[n]-1
499 void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
500 int i;
501 m->shiftsleft = 4;
502 m->entries = n;
503 m->syms = sym;
504 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
505 for (i = 0; i < n; i++) {
506 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
507 m->syms[i].sym = i+s; /* actual symbol */
508 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
510 m->syms[n].cumfreq = 0;
513 /******************************************************************
514 * QTMfdi_init (internal)
516 int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
517 int wndsize = 1 << window, msz = window * 2, i;
518 cab_ULONG j;
520 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
521 /* if a previously allocated window is big enough, keep it */
522 if (window < 10 || window > 21) return DECR_DATAFORMAT;
523 if (QTM(actual_size) < wndsize) {
524 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
525 QTM(window) = NULL;
527 if (!QTM(window)) {
528 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
529 QTM(actual_size) = wndsize;
531 QTM(window_size) = wndsize;
532 QTM(window_posn) = 0;
534 /* initialise static slot/extrabits tables */
535 for (i = 0, j = 0; i < 27; i++) {
536 q_length_extra[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
537 q_length_base[i] = j; j += 1 << ((i == 26) ? 5 : q_length_extra[i]);
539 for (i = 0, j = 0; i < 42; i++) {
540 q_extra_bits[i] = (i < 2 ? 0 : i-2) >> 1;
541 q_position_base[i] = j; j += 1 << q_extra_bits[i];
544 /* initialise arithmetic coding models */
546 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
548 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
549 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
550 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
551 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
553 /* model 4 depends on table size, ranges from 20 to 24 */
554 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
555 /* model 5 depends on table size, ranges from 20 to 36 */
556 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
557 /* model 6pos depends on table size, ranges from 20 to 42 */
558 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
559 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
561 return DECR_OK;
564 /* FIXME: Eliminate global variables */
565 static cab_ULONG lzx_position_base[51];
566 static cab_UBYTE extra_bits[51];
568 /************************************************************
569 * LZXfdi_init (internal)
571 int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
572 cab_ULONG wndsize = 1 << window;
573 int i, j, posn_slots;
575 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
576 /* if a previously allocated window is big enough, keep it */
577 if (window < 15 || window > 21) return DECR_DATAFORMAT;
578 if (LZX(actual_size) < wndsize) {
579 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
580 LZX(window) = NULL;
582 if (!LZX(window)) {
583 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
584 LZX(actual_size) = wndsize;
586 LZX(window_size) = wndsize;
588 /* initialise static tables */
589 for (i=0, j=0; i <= 50; i += 2) {
590 extra_bits[i] = extra_bits[i+1] = j; /* 0,0,0,0,1,1,2,2,3,3... */
591 if ((i != 0) && (j < 17)) j++; /* 0,0,1,2,3,4...15,16,17,17,17,17... */
593 for (i=0, j=0; i <= 50; i++) {
594 lzx_position_base[i] = j; /* 0,1,2,3,4,6,8,12,16,24,32,... */
595 j += 1 << extra_bits[i]; /* 1,1,1,1,2,2,4,4,8,8,16,16,32,32,... */
598 /* calculate required position slots */
599 if (window == 20) posn_slots = 42;
600 else if (window == 21) posn_slots = 50;
601 else posn_slots = window << 1;
603 /*posn_slots=i=0; while (i < wndsize) i += 1 << extra_bits[posn_slots++]; */
605 LZX(R0) = LZX(R1) = LZX(R2) = 1;
606 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
607 LZX(header_read) = 0;
608 LZX(frames_read) = 0;
609 LZX(block_remaining) = 0;
610 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
611 LZX(intel_curpos) = 0;
612 LZX(intel_started) = 0;
613 LZX(window_posn) = 0;
615 /* initialise tables to 0 (because deltas will be applied to them) */
616 for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) LZX(MAINTREE_len)[i] = 0;
617 for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) LZX(LENGTH_len)[i] = 0;
619 return DECR_OK;
622 /****************************************************
623 * NONEfdi_decomp(internal)
625 int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
627 if (inlen != outlen) return DECR_ILLEGALDATA;
628 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
629 return DECR_OK;
632 /********************************************************
633 * Ziphuft_free (internal)
635 void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
637 register struct Ziphuft *p, *q;
639 /* Go through linked list, freeing from the allocated (t[-1]) address. */
640 p = t;
641 while (p != (struct Ziphuft *)NULL)
643 q = (--p)->v.t;
644 PFDI_FREE(hfdi, p);
645 p = q;
649 /*********************************************************
650 * fdi_Ziphuft_build (internal)
652 cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, cab_UWORD *d, cab_UWORD *e,
653 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
655 cab_ULONG a; /* counter for codes of length k */
656 cab_ULONG el; /* length of EOB code (value 256) */
657 cab_ULONG f; /* i repeats in table every f entries */
658 cab_LONG g; /* maximum code length */
659 cab_LONG h; /* table level */
660 register cab_ULONG i; /* counter, current code */
661 register cab_ULONG j; /* counter */
662 register cab_LONG k; /* number of bits in current code */
663 cab_LONG *l; /* stack of bits per table */
664 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
665 register struct Ziphuft *q; /* points to current table */
666 struct Ziphuft r; /* table entry for structure assignment */
667 register cab_LONG w; /* bits before this table == (l * h) */
668 cab_ULONG *xp; /* pointer into x */
669 cab_LONG y; /* number of dummy codes added */
670 cab_ULONG z; /* number of entries in current table */
672 l = ZIP(lx)+1;
674 /* Generate counts for each bit length */
675 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
677 for(i = 0; i < ZIPBMAX+1; ++i)
678 ZIP(c)[i] = 0;
679 p = b; i = n;
682 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
683 } while (--i);
684 if (ZIP(c)[0] == n) /* null input--all zero length codes */
686 *t = (struct Ziphuft *)NULL;
687 *m = 0;
688 return 0;
691 /* Find minimum and maximum length, bound *m by those */
692 for (j = 1; j <= ZIPBMAX; j++)
693 if (ZIP(c)[j])
694 break;
695 k = j; /* minimum code length */
696 if ((cab_ULONG)*m < j)
697 *m = j;
698 for (i = ZIPBMAX; i; i--)
699 if (ZIP(c)[i])
700 break;
701 g = i; /* maximum code length */
702 if ((cab_ULONG)*m > i)
703 *m = i;
705 /* Adjust last length count to fill out codes, if needed */
706 for (y = 1 << j; j < i; j++, y <<= 1)
707 if ((y -= ZIP(c)[j]) < 0)
708 return 2; /* bad input: more codes than bits */
709 if ((y -= ZIP(c)[i]) < 0)
710 return 2;
711 ZIP(c)[i] += y;
713 /* Generate starting offsets LONGo the value table for each length */
714 ZIP(x)[1] = j = 0;
715 p = ZIP(c) + 1; xp = ZIP(x) + 2;
716 while (--i)
717 { /* note that i == g from above */
718 *xp++ = (j += *p++);
721 /* Make a table of values in order of bit lengths */
722 p = b; i = 0;
724 if ((j = *p++) != 0)
725 ZIP(v)[ZIP(x)[j]++] = i;
726 } while (++i < n);
729 /* Generate the Huffman codes and for each, make the table entries */
730 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
731 p = ZIP(v); /* grab values in bit order */
732 h = -1; /* no tables yet--level -1 */
733 w = l[-1] = 0; /* no bits decoded yet */
734 ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */
735 q = (struct Ziphuft *)NULL; /* ditto */
736 z = 0; /* ditto */
738 /* go through the bit lengths (k already is bits in shortest code) */
739 for (; k <= g; k++)
741 a = ZIP(c)[k];
742 while (a--)
744 /* here i is the Huffman code of length k bits for value *p */
745 /* make tables up to required level */
746 while (k > w + l[h])
748 w += l[h++]; /* add bits already decoded */
750 /* compute minimum size table less than or equal to *m bits */
751 z = (z = g - w) > (cab_ULONG)*m ? *m : z; /* upper limit */
752 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
753 { /* too few codes for k-w bit table */
754 f -= a + 1; /* deduct codes from patterns left */
755 xp = ZIP(c) + k;
756 while (++j < z) /* try smaller tables up to z bits */
758 if ((f <<= 1) <= *++xp)
759 break; /* enough codes to use up j bits */
760 f -= *xp; /* else deduct codes from patterns */
763 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
764 j = el - w; /* make EOB code end at table */
765 z = 1 << j; /* table entries for j-bit table */
766 l[h] = j; /* set table size in stack */
768 /* allocate and link in new table */
769 if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
771 if(h)
772 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
773 return 3; /* not enough memory */
775 *t = q + 1; /* link to list for Ziphuft_free() */
776 *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
777 ZIP(u)[h] = ++q; /* table starts after link */
779 /* connect to last table, if there is one */
780 if (h)
782 ZIP(x)[h] = i; /* save pattern for backing up */
783 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
784 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
785 r.v.t = q; /* pointer to this table */
786 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
787 ZIP(u)[h-1][j] = r; /* connect to last table */
791 /* set up table entry in r */
792 r.b = (cab_UBYTE)(k - w);
793 if (p >= ZIP(v) + n)
794 r.e = 99; /* out of values--invalid code */
795 else if (*p < s)
797 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
798 r.v.n = *p++; /* simple code is just the value */
800 else
802 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
803 r.v.n = d[*p++ - s];
806 /* fill code-like entries with r */
807 f = 1 << (k - w);
808 for (j = i >> w; j < z; j += f)
809 q[j] = r;
811 /* backwards increment the k-bit code i */
812 for (j = 1 << (k - 1); i & j; j >>= 1)
813 i ^= j;
814 i ^= j;
816 /* backup over finished tables */
817 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
818 w -= l[--h]; /* don't need to update q */
822 /* return actual size of base table */
823 *m = l[0];
825 /* Return true (1) if we were given an incomplete table */
826 return y != 0 && g != 1;
829 /*********************************************************
830 * fdi_Zipinflate_codes (internal)
832 cab_LONG fdi_Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td,
833 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
835 register cab_ULONG e; /* table entry flag/number of extra bits */
836 cab_ULONG n, d; /* length and index for copy */
837 cab_ULONG w; /* current window position */
838 struct Ziphuft *t; /* pointer to table entry */
839 cab_ULONG ml, md; /* masks for bl and bd bits */
840 register cab_ULONG b; /* bit buffer */
841 register cab_ULONG k; /* number of bits in bit buffer */
843 /* make local copies of globals */
844 b = ZIP(bb); /* initialize bit buffer */
845 k = ZIP(bk);
846 w = ZIP(window_posn); /* initialize window position */
848 /* inflate the coded data */
849 ml = Zipmask[bl]; /* precompute masks for speed */
850 md = Zipmask[bd];
852 for(;;)
854 ZIPNEEDBITS((cab_ULONG)bl)
855 if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16)
858 if (e == 99)
859 return 1;
860 ZIPDUMPBITS(t->b)
861 e -= 16;
862 ZIPNEEDBITS(e)
863 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
864 ZIPDUMPBITS(t->b)
865 if (e == 16) /* then it's a literal */
866 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
867 else /* it's an EOB or a length */
869 /* exit if end of block */
870 if(e == 15)
871 break;
873 /* get length of block to copy */
874 ZIPNEEDBITS(e)
875 n = t->v.n + ((cab_ULONG)b & Zipmask[e]);
876 ZIPDUMPBITS(e);
878 /* decode distance of block to copy */
879 ZIPNEEDBITS((cab_ULONG)bd)
880 if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16)
881 do {
882 if (e == 99)
883 return 1;
884 ZIPDUMPBITS(t->b)
885 e -= 16;
886 ZIPNEEDBITS(e)
887 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
888 ZIPDUMPBITS(t->b)
889 ZIPNEEDBITS(e)
890 d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]);
891 ZIPDUMPBITS(e)
894 n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
897 CAB(outbuf)[w++] = CAB(outbuf)[d++];
898 } while (--e);
899 } while (n);
903 /* restore the globals from the locals */
904 ZIP(window_posn) = w; /* restore global window pointer */
905 ZIP(bb) = b; /* restore global bit buffer */
906 ZIP(bk) = k;
908 /* done */
909 return 0;
912 /***********************************************************
913 * Zipinflate_stored (internal)
915 cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
916 /* "decompress" an inflated type 0 (stored) block. */
918 cab_ULONG n; /* number of bytes in block */
919 cab_ULONG w; /* current window position */
920 register cab_ULONG b; /* bit buffer */
921 register cab_ULONG k; /* number of bits in bit buffer */
923 /* make local copies of globals */
924 b = ZIP(bb); /* initialize bit buffer */
925 k = ZIP(bk);
926 w = ZIP(window_posn); /* initialize window position */
928 /* go to byte boundary */
929 n = k & 7;
930 ZIPDUMPBITS(n);
932 /* get the length and its complement */
933 ZIPNEEDBITS(16)
934 n = ((cab_ULONG)b & 0xffff);
935 ZIPDUMPBITS(16)
936 ZIPNEEDBITS(16)
937 if (n != (cab_ULONG)((~b) & 0xffff))
938 return 1; /* error in compressed data */
939 ZIPDUMPBITS(16)
941 /* read and output the compressed data */
942 while(n--)
944 ZIPNEEDBITS(8)
945 CAB(outbuf)[w++] = (cab_UBYTE)b;
946 ZIPDUMPBITS(8)
949 /* restore the globals from the locals */
950 ZIP(window_posn) = w; /* restore global window pointer */
951 ZIP(bb) = b; /* restore global bit buffer */
952 ZIP(bk) = k;
953 return 0;
956 /******************************************************
957 * fdi_Zipinflate_fixed (internal)
959 cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
961 struct Ziphuft *fixed_tl;
962 struct Ziphuft *fixed_td;
963 cab_LONG fixed_bl, fixed_bd;
964 cab_LONG i; /* temporary variable */
965 cab_ULONG *l;
967 l = ZIP(ll);
969 /* literal table */
970 for(i = 0; i < 144; i++)
971 l[i] = 8;
972 for(; i < 256; i++)
973 l[i] = 9;
974 for(; i < 280; i++)
975 l[i] = 7;
976 for(; i < 288; i++) /* make a complete, but wrong code set */
977 l[i] = 8;
978 fixed_bl = 7;
979 if((i = fdi_Ziphuft_build(l, 288, 257, (cab_UWORD *) Zipcplens,
980 (cab_UWORD *) Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
981 return i;
983 /* distance table */
984 for(i = 0; i < 30; i++) /* make an incomplete code set */
985 l[i] = 5;
986 fixed_bd = 5;
987 if((i = fdi_Ziphuft_build(l, 30, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
988 &fixed_td, &fixed_bd, decomp_state)) > 1)
990 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
991 return i;
994 /* decompress until an end-of-block code */
995 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
997 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
998 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
999 return i;
1002 /**************************************************************
1003 * fdi_Zipinflate_dynamic (internal)
1005 cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1006 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1008 cab_LONG i; /* temporary variables */
1009 cab_ULONG j;
1010 cab_ULONG *ll;
1011 cab_ULONG l; /* last length */
1012 cab_ULONG m; /* mask for bit lengths table */
1013 cab_ULONG n; /* number of lengths to get */
1014 struct Ziphuft *tl; /* literal/length code table */
1015 struct Ziphuft *td; /* distance code table */
1016 cab_LONG bl; /* lookup bits for tl */
1017 cab_LONG bd; /* lookup bits for td */
1018 cab_ULONG nb; /* number of bit length codes */
1019 cab_ULONG nl; /* number of literal/length codes */
1020 cab_ULONG nd; /* number of distance codes */
1021 register cab_ULONG b; /* bit buffer */
1022 register cab_ULONG k; /* number of bits in bit buffer */
1024 /* make local bit buffer */
1025 b = ZIP(bb);
1026 k = ZIP(bk);
1027 ll = ZIP(ll);
1029 /* read in table lengths */
1030 ZIPNEEDBITS(5)
1031 nl = 257 + ((cab_ULONG)b & 0x1f); /* number of literal/length codes */
1032 ZIPDUMPBITS(5)
1033 ZIPNEEDBITS(5)
1034 nd = 1 + ((cab_ULONG)b & 0x1f); /* number of distance codes */
1035 ZIPDUMPBITS(5)
1036 ZIPNEEDBITS(4)
1037 nb = 4 + ((cab_ULONG)b & 0xf); /* number of bit length codes */
1038 ZIPDUMPBITS(4)
1039 if(nl > 288 || nd > 32)
1040 return 1; /* bad lengths */
1042 /* read in bit-length-code lengths */
1043 for(j = 0; j < nb; j++)
1045 ZIPNEEDBITS(3)
1046 ll[Zipborder[j]] = (cab_ULONG)b & 7;
1047 ZIPDUMPBITS(3)
1049 for(; j < 19; j++)
1050 ll[Zipborder[j]] = 0;
1052 /* build decoding table for trees--single level, 7 bit lookup */
1053 bl = 7;
1054 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1056 if(i == 1)
1057 fdi_Ziphuft_free(CAB(hfdi), tl);
1058 return i; /* incomplete code set */
1061 /* read in literal and distance code lengths */
1062 n = nl + nd;
1063 m = Zipmask[bl];
1064 i = l = 0;
1065 while((cab_ULONG)i < n)
1067 ZIPNEEDBITS((cab_ULONG)bl)
1068 j = (td = tl + ((cab_ULONG)b & m))->b;
1069 ZIPDUMPBITS(j)
1070 j = td->v.n;
1071 if (j < 16) /* length of code in bits (0..15) */
1072 ll[i++] = l = j; /* save last length in l */
1073 else if (j == 16) /* repeat last length 3 to 6 times */
1075 ZIPNEEDBITS(2)
1076 j = 3 + ((cab_ULONG)b & 3);
1077 ZIPDUMPBITS(2)
1078 if((cab_ULONG)i + j > n)
1079 return 1;
1080 while (j--)
1081 ll[i++] = l;
1083 else if (j == 17) /* 3 to 10 zero length codes */
1085 ZIPNEEDBITS(3)
1086 j = 3 + ((cab_ULONG)b & 7);
1087 ZIPDUMPBITS(3)
1088 if ((cab_ULONG)i + j > n)
1089 return 1;
1090 while (j--)
1091 ll[i++] = 0;
1092 l = 0;
1094 else /* j == 18: 11 to 138 zero length codes */
1096 ZIPNEEDBITS(7)
1097 j = 11 + ((cab_ULONG)b & 0x7f);
1098 ZIPDUMPBITS(7)
1099 if ((cab_ULONG)i + j > n)
1100 return 1;
1101 while (j--)
1102 ll[i++] = 0;
1103 l = 0;
1107 /* free decoding table for trees */
1108 fdi_Ziphuft_free(CAB(hfdi), tl);
1110 /* restore the global bit buffer */
1111 ZIP(bb) = b;
1112 ZIP(bk) = k;
1114 /* build the decoding tables for literal/length and distance codes */
1115 bl = ZIPLBITS;
1116 if((i = fdi_Ziphuft_build(ll, nl, 257, (cab_UWORD *) Zipcplens, (cab_UWORD *) Zipcplext,
1117 &tl, &bl, decomp_state)) != 0)
1119 if(i == 1)
1120 fdi_Ziphuft_free(CAB(hfdi), tl);
1121 return i; /* incomplete code set */
1123 bd = ZIPDBITS;
1124 fdi_Ziphuft_build(ll + nl, nd, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
1125 &td, &bd, decomp_state);
1127 /* decompress until an end-of-block code */
1128 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1129 return 1;
1131 /* free the decoding tables, return */
1132 fdi_Ziphuft_free(CAB(hfdi), tl);
1133 fdi_Ziphuft_free(CAB(hfdi), td);
1134 return 0;
1137 /*****************************************************
1138 * fdi_Zipinflate_block (internal)
1140 cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1141 { /* decompress an inflated block */
1142 cab_ULONG t; /* block type */
1143 register cab_ULONG b; /* bit buffer */
1144 register cab_ULONG k; /* number of bits in bit buffer */
1146 /* make local bit buffer */
1147 b = ZIP(bb);
1148 k = ZIP(bk);
1150 /* read in last block bit */
1151 ZIPNEEDBITS(1)
1152 *e = (cab_LONG)b & 1;
1153 ZIPDUMPBITS(1)
1155 /* read in block type */
1156 ZIPNEEDBITS(2)
1157 t = (cab_ULONG)b & 3;
1158 ZIPDUMPBITS(2)
1160 /* restore the global bit buffer */
1161 ZIP(bb) = b;
1162 ZIP(bk) = k;
1164 /* inflate that block type */
1165 if(t == 2)
1166 return fdi_Zipinflate_dynamic(decomp_state);
1167 if(t == 0)
1168 return fdi_Zipinflate_stored(decomp_state);
1169 if(t == 1)
1170 return fdi_Zipinflate_fixed(decomp_state);
1171 /* bad block type */
1172 return 2;
1175 /****************************************************
1176 * ZIPfdi_decomp(internal)
1178 int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1180 cab_LONG e; /* last block flag */
1182 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1184 ZIP(inpos) = CAB(inbuf);
1185 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1186 if(outlen > ZIPWSIZE)
1187 return DECR_DATAFORMAT;
1189 /* CK = Chris Kirmse, official Microsoft purloiner */
1190 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1191 return DECR_ILLEGALDATA;
1192 ZIP(inpos) += 2;
1194 do {
1195 if(fdi_Zipinflate_block(&e, decomp_state))
1196 return DECR_ILLEGALDATA;
1197 } while(!e);
1199 /* return success */
1200 return DECR_OK;
1203 /*******************************************************************
1204 * QTMfdi_decomp(internal)
1206 int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1208 cab_UBYTE *inpos = CAB(inbuf);
1209 cab_UBYTE *window = QTM(window);
1210 cab_UBYTE *runsrc, *rundest;
1212 cab_ULONG window_posn = QTM(window_posn);
1213 cab_ULONG window_size = QTM(window_size);
1215 /* used by bitstream macros */
1216 register int bitsleft, bitrun, bitsneed;
1217 register cab_ULONG bitbuf;
1219 /* used by GET_SYMBOL */
1220 cab_ULONG range;
1221 cab_UWORD symf;
1222 int i;
1224 int extra, togo = outlen, match_length = 0, copy_length;
1225 cab_UBYTE selector, sym;
1226 cab_ULONG match_offset = 0;
1228 cab_UWORD H = 0xFFFF, L = 0, C;
1230 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1232 /* read initial value of C */
1233 Q_INIT_BITSTREAM;
1234 Q_READ_BITS(C, 16);
1236 /* apply 2^x-1 mask */
1237 window_posn &= window_size - 1;
1238 /* runs can't straddle the window wraparound */
1239 if ((window_posn + togo) > window_size) {
1240 TRACE("straddled run\n");
1241 return DECR_DATAFORMAT;
1244 while (togo > 0) {
1245 GET_SYMBOL(model7, selector);
1246 switch (selector) {
1247 case 0:
1248 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1249 break;
1250 case 1:
1251 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1252 break;
1253 case 2:
1254 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1255 break;
1256 case 3:
1257 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1258 break;
1260 case 4:
1261 /* selector 4 = fixed length of 3 */
1262 GET_SYMBOL(model4, sym);
1263 Q_READ_BITS(extra, q_extra_bits[sym]);
1264 match_offset = q_position_base[sym] + extra + 1;
1265 match_length = 3;
1266 break;
1268 case 5:
1269 /* selector 5 = fixed length of 4 */
1270 GET_SYMBOL(model5, sym);
1271 Q_READ_BITS(extra, q_extra_bits[sym]);
1272 match_offset = q_position_base[sym] + extra + 1;
1273 match_length = 4;
1274 break;
1276 case 6:
1277 /* selector 6 = variable length */
1278 GET_SYMBOL(model6len, sym);
1279 Q_READ_BITS(extra, q_length_extra[sym]);
1280 match_length = q_length_base[sym] + extra + 5;
1281 GET_SYMBOL(model6pos, sym);
1282 Q_READ_BITS(extra, q_extra_bits[sym]);
1283 match_offset = q_position_base[sym] + extra + 1;
1284 break;
1286 default:
1287 TRACE("Selector is bogus\n");
1288 return DECR_ILLEGALDATA;
1291 /* if this is a match */
1292 if (selector >= 4) {
1293 rundest = window + window_posn;
1294 togo -= match_length;
1296 /* copy any wrapped around source data */
1297 if (window_posn >= match_offset) {
1298 /* no wrap */
1299 runsrc = rundest - match_offset;
1300 } else {
1301 runsrc = rundest + (window_size - match_offset);
1302 copy_length = match_offset - window_posn;
1303 if (copy_length < match_length) {
1304 match_length -= copy_length;
1305 window_posn += copy_length;
1306 while (copy_length-- > 0) *rundest++ = *runsrc++;
1307 runsrc = window;
1310 window_posn += match_length;
1312 /* copy match data - no worries about destination wraps */
1313 while (match_length-- > 0) *rundest++ = *runsrc++;
1315 } /* while (togo > 0) */
1317 if (togo != 0) {
1318 TRACE("Frame overflow, this_run = %d\n", togo);
1319 return DECR_ILLEGALDATA;
1322 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1323 outlen, outlen);
1325 QTM(window_posn) = window_posn;
1326 return DECR_OK;
1329 /************************************************************
1330 * fdi_lzx_read_lens (internal)
1332 int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1333 fdi_decomp_state *decomp_state) {
1334 cab_ULONG i,j, x,y;
1335 int z;
1337 register cab_ULONG bitbuf = lb->bb;
1338 register int bitsleft = lb->bl;
1339 cab_UBYTE *inpos = lb->ip;
1340 cab_UWORD *hufftbl;
1342 for (x = 0; x < 20; x++) {
1343 READ_BITS(y, 4);
1344 LENTABLE(PRETREE)[x] = y;
1346 BUILD_TABLE(PRETREE);
1348 for (x = first; x < last; ) {
1349 READ_HUFFSYM(PRETREE, z);
1350 if (z == 17) {
1351 READ_BITS(y, 4); y += 4;
1352 while (y--) lens[x++] = 0;
1354 else if (z == 18) {
1355 READ_BITS(y, 5); y += 20;
1356 while (y--) lens[x++] = 0;
1358 else if (z == 19) {
1359 READ_BITS(y, 1); y += 4;
1360 READ_HUFFSYM(PRETREE, z);
1361 z = lens[x] - z; if (z < 0) z += 17;
1362 while (y--) lens[x++] = z;
1364 else {
1365 z = lens[x] - z; if (z < 0) z += 17;
1366 lens[x++] = z;
1370 lb->bb = bitbuf;
1371 lb->bl = bitsleft;
1372 lb->ip = inpos;
1373 return 0;
1376 /*******************************************************
1377 * LZXfdi_decomp(internal)
1379 int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1380 cab_UBYTE *inpos = CAB(inbuf);
1381 cab_UBYTE *endinp = inpos + inlen;
1382 cab_UBYTE *window = LZX(window);
1383 cab_UBYTE *runsrc, *rundest;
1384 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1386 cab_ULONG window_posn = LZX(window_posn);
1387 cab_ULONG window_size = LZX(window_size);
1388 cab_ULONG R0 = LZX(R0);
1389 cab_ULONG R1 = LZX(R1);
1390 cab_ULONG R2 = LZX(R2);
1392 register cab_ULONG bitbuf;
1393 register int bitsleft;
1394 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1395 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1397 int togo = outlen, this_run, main_element, aligned_bits;
1398 int match_length, copy_length, length_footer, extra, verbatim_bits;
1400 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1402 INIT_BITSTREAM;
1404 /* read header if necessary */
1405 if (!LZX(header_read)) {
1406 i = j = 0;
1407 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1408 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1409 LZX(header_read) = 1;
1412 /* main decoding loop */
1413 while (togo > 0) {
1414 /* last block finished, new block expected */
1415 if (LZX(block_remaining) == 0) {
1416 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1417 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1418 INIT_BITSTREAM;
1421 READ_BITS(LZX(block_type), 3);
1422 READ_BITS(i, 16);
1423 READ_BITS(j, 8);
1424 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1426 switch (LZX(block_type)) {
1427 case LZX_BLOCKTYPE_ALIGNED:
1428 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1429 BUILD_TABLE(ALIGNED);
1430 /* rest of aligned header is same as verbatim */
1432 case LZX_BLOCKTYPE_VERBATIM:
1433 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1434 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1435 BUILD_TABLE(MAINTREE);
1436 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1438 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1439 BUILD_TABLE(LENGTH);
1440 break;
1442 case LZX_BLOCKTYPE_UNCOMPRESSED:
1443 LZX(intel_started) = 1; /* because we can't assume otherwise */
1444 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1445 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1446 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1447 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1448 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1449 break;
1451 default:
1452 return DECR_ILLEGALDATA;
1456 /* buffer exhaustion check */
1457 if (inpos > endinp) {
1458 /* it's possible to have a file where the next run is less than
1459 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1460 * in building the tables will exhaust the buffer, so we should
1461 * allow for this, but not allow those accidentally read bits to
1462 * be used (so we check that there are at least 16 bits
1463 * remaining - in this boundary case they aren't really part of
1464 * the compressed data)
1466 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1469 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1470 if (this_run > togo) this_run = togo;
1471 togo -= this_run;
1472 LZX(block_remaining) -= this_run;
1474 /* apply 2^x-1 mask */
1475 window_posn &= window_size - 1;
1476 /* runs can't straddle the window wraparound */
1477 if ((window_posn + this_run) > window_size)
1478 return DECR_DATAFORMAT;
1480 switch (LZX(block_type)) {
1482 case LZX_BLOCKTYPE_VERBATIM:
1483 while (this_run > 0) {
1484 READ_HUFFSYM(MAINTREE, main_element);
1486 if (main_element < LZX_NUM_CHARS) {
1487 /* literal: 0 to LZX_NUM_CHARS-1 */
1488 window[window_posn++] = main_element;
1489 this_run--;
1491 else {
1492 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1493 main_element -= LZX_NUM_CHARS;
1495 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1496 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1497 READ_HUFFSYM(LENGTH, length_footer);
1498 match_length += length_footer;
1500 match_length += LZX_MIN_MATCH;
1502 match_offset = main_element >> 3;
1504 if (match_offset > 2) {
1505 /* not repeated offset */
1506 if (match_offset != 3) {
1507 extra = extra_bits[match_offset];
1508 READ_BITS(verbatim_bits, extra);
1509 match_offset = lzx_position_base[match_offset]
1510 - 2 + verbatim_bits;
1512 else {
1513 match_offset = 1;
1516 /* update repeated offset LRU queue */
1517 R2 = R1; R1 = R0; R0 = match_offset;
1519 else if (match_offset == 0) {
1520 match_offset = R0;
1522 else if (match_offset == 1) {
1523 match_offset = R1;
1524 R1 = R0; R0 = match_offset;
1526 else /* match_offset == 2 */ {
1527 match_offset = R2;
1528 R2 = R0; R0 = match_offset;
1531 rundest = window + window_posn;
1532 this_run -= match_length;
1534 /* copy any wrapped around source data */
1535 if (window_posn >= match_offset) {
1536 /* no wrap */
1537 runsrc = rundest - match_offset;
1538 } else {
1539 runsrc = rundest + (window_size - match_offset);
1540 copy_length = match_offset - window_posn;
1541 if (copy_length < match_length) {
1542 match_length -= copy_length;
1543 window_posn += copy_length;
1544 while (copy_length-- > 0) *rundest++ = *runsrc++;
1545 runsrc = window;
1548 window_posn += match_length;
1550 /* copy match data - no worries about destination wraps */
1551 while (match_length-- > 0) *rundest++ = *runsrc++;
1554 break;
1556 case LZX_BLOCKTYPE_ALIGNED:
1557 while (this_run > 0) {
1558 READ_HUFFSYM(MAINTREE, main_element);
1560 if (main_element < LZX_NUM_CHARS) {
1561 /* literal: 0 to LZX_NUM_CHARS-1 */
1562 window[window_posn++] = main_element;
1563 this_run--;
1565 else {
1566 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1567 main_element -= LZX_NUM_CHARS;
1569 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1570 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1571 READ_HUFFSYM(LENGTH, length_footer);
1572 match_length += length_footer;
1574 match_length += LZX_MIN_MATCH;
1576 match_offset = main_element >> 3;
1578 if (match_offset > 2) {
1579 /* not repeated offset */
1580 extra = extra_bits[match_offset];
1581 match_offset = lzx_position_base[match_offset] - 2;
1582 if (extra > 3) {
1583 /* verbatim and aligned bits */
1584 extra -= 3;
1585 READ_BITS(verbatim_bits, extra);
1586 match_offset += (verbatim_bits << 3);
1587 READ_HUFFSYM(ALIGNED, aligned_bits);
1588 match_offset += aligned_bits;
1590 else if (extra == 3) {
1591 /* aligned bits only */
1592 READ_HUFFSYM(ALIGNED, aligned_bits);
1593 match_offset += aligned_bits;
1595 else if (extra > 0) { /* extra==1, extra==2 */
1596 /* verbatim bits only */
1597 READ_BITS(verbatim_bits, extra);
1598 match_offset += verbatim_bits;
1600 else /* extra == 0 */ {
1601 /* ??? */
1602 match_offset = 1;
1605 /* update repeated offset LRU queue */
1606 R2 = R1; R1 = R0; R0 = match_offset;
1608 else if (match_offset == 0) {
1609 match_offset = R0;
1611 else if (match_offset == 1) {
1612 match_offset = R1;
1613 R1 = R0; R0 = match_offset;
1615 else /* match_offset == 2 */ {
1616 match_offset = R2;
1617 R2 = R0; R0 = match_offset;
1620 rundest = window + window_posn;
1621 this_run -= match_length;
1623 /* copy any wrapped around source data */
1624 if (window_posn >= match_offset) {
1625 /* no wrap */
1626 runsrc = rundest - match_offset;
1627 } else {
1628 runsrc = rundest + (window_size - match_offset);
1629 copy_length = match_offset - window_posn;
1630 if (copy_length < match_length) {
1631 match_length -= copy_length;
1632 window_posn += copy_length;
1633 while (copy_length-- > 0) *rundest++ = *runsrc++;
1634 runsrc = window;
1637 window_posn += match_length;
1639 /* copy match data - no worries about destination wraps */
1640 while (match_length-- > 0) *rundest++ = *runsrc++;
1643 break;
1645 case LZX_BLOCKTYPE_UNCOMPRESSED:
1646 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1647 memcpy(window + window_posn, inpos, (size_t) this_run);
1648 inpos += this_run; window_posn += this_run;
1649 break;
1651 default:
1652 return DECR_ILLEGALDATA; /* might as well */
1658 if (togo != 0) return DECR_ILLEGALDATA;
1659 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1660 outlen, (size_t) outlen);
1662 LZX(window_posn) = window_posn;
1663 LZX(R0) = R0;
1664 LZX(R1) = R1;
1665 LZX(R2) = R2;
1667 /* intel E8 decoding */
1668 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1669 if (outlen <= 6 || !LZX(intel_started)) {
1670 LZX(intel_curpos) += outlen;
1672 else {
1673 cab_UBYTE *data = CAB(outbuf);
1674 cab_UBYTE *dataend = data + outlen - 10;
1675 cab_LONG curpos = LZX(intel_curpos);
1676 cab_LONG filesize = LZX(intel_filesize);
1677 cab_LONG abs_off, rel_off;
1679 LZX(intel_curpos) = curpos + outlen;
1681 while (data < dataend) {
1682 if (*data++ != 0xE8) { curpos++; continue; }
1683 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1684 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1685 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1686 data[0] = (cab_UBYTE) rel_off;
1687 data[1] = (cab_UBYTE) (rel_off >> 8);
1688 data[2] = (cab_UBYTE) (rel_off >> 16);
1689 data[3] = (cab_UBYTE) (rel_off >> 24);
1691 data += 4;
1692 curpos += 5;
1696 return DECR_OK;
1699 /**********************************************************
1700 * fdi_decomp (internal)
1702 int fdi_decomp(struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state)
1704 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
1705 cab_UBYTE buf[cfdata_SIZEOF], *data;
1706 cab_UWORD inlen, len, outlen, cando;
1707 cab_ULONG cksum;
1708 cab_LONG err;
1710 TRACE("(fi == ^%p, savemode == %d)\n", fi, savemode);
1712 while (bytes > 0) {
1713 /* cando = the max number of bytes we can do */
1714 cando = CAB(outlen);
1715 if (cando > bytes) cando = bytes;
1717 /* if cando != 0 */
1718 if (cando && savemode)
1719 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
1721 CAB(outpos) += cando;
1722 CAB(outlen) -= cando;
1723 bytes -= cando; if (!bytes) break;
1725 /* we only get here if we emptied the output buffer */
1727 /* read data header + data */
1728 inlen = outlen = 0;
1729 while (outlen == 0) {
1730 /* read the block header, skip the reserved part */
1731 if (PFDI_READ(CAB(hfdi), CAB(cabhf), buf, cfdata_SIZEOF) != cfdata_SIZEOF)
1732 return DECR_INPUT;
1734 if (PFDI_SEEK(CAB(hfdi), CAB(cabhf), CAB(block_resv), SEEK_CUR) == -1)
1735 return DECR_INPUT;
1737 /* we shouldn't get blocks over CAB_INPUTMAX in size */
1738 data = CAB(inbuf) + inlen;
1739 len = EndGetI16(buf+cfdata_CompressedSize);
1740 inlen += len;
1741 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
1742 if (PFDI_READ(CAB(hfdi), CAB(cabhf), data, len) != len)
1743 return DECR_INPUT;
1745 /* clear two bytes after read-in data */
1746 data[len+1] = data[len+2] = 0;
1748 /* perform checksum test on the block (if one is stored) */
1749 cksum = EndGetI32(buf+cfdata_CheckSum);
1750 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
1751 return DECR_CHECKSUM; /* checksum is wrong */
1753 /* outlen=0 means this block was part of a split block */
1754 outlen = EndGetI16(buf+cfdata_UncompressedSize);
1755 if (outlen == 0) {
1757 cabinet_close(cab);
1758 cab = CAB(current)->cab[++CAB(split)];
1759 if (!cabinet_open(cab)) return DECR_INPUT;
1760 cabinet_seek(cab, CAB(current)->offset[CAB(split)]); */
1761 FIXME("split block... ack! fix this.\n");
1762 return DECR_INPUT;
1766 /* decompress block */
1767 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
1768 return err;
1769 CAB(outlen) = outlen;
1770 CAB(outpos) = CAB(outbuf);
1773 return DECR_OK;
1776 /***********************************************************************
1777 * FDICopy (CABINET.22)
1779 BOOL __cdecl FDICopy(
1780 HFDI hfdi,
1781 char *pszCabinet,
1782 char *pszCabPath,
1783 int flags,
1784 PFNFDINOTIFY pfnfdin,
1785 PFNFDIDECRYPT pfnfdid,
1786 void *pvUser)
1788 FDICABINETINFO fdici;
1789 FDINOTIFICATION fdin;
1790 MORE_ISCAB_INFO mii;
1791 int cabhf, filehf;
1792 int i, idx;
1793 char fullpath[MAX_PATH];
1794 size_t pathlen, filenamelen;
1795 char emptystring = '\0';
1796 cab_UBYTE buf[64];
1797 BOOL initialcab = TRUE;
1798 struct fdi_folder *fol = NULL, *linkfol = NULL;
1799 struct fdi_file *file = NULL, *linkfile = NULL;
1800 fdi_decomp_state _decomp_state;
1801 fdi_decomp_state *decomp_state = &_decomp_state;
1803 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, \
1804 pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
1805 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
1807 if (!REALLY_IS_FDI(hfdi)) {
1808 SetLastError(ERROR_INVALID_HANDLE);
1809 return FALSE;
1812 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
1814 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
1815 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
1817 /* slight overestimation here to save CPU cycles in the developer's brain */
1818 if ((pathlen + filenamelen + 3) > MAX_PATH) {
1819 ERR("MAX_PATH exceeded.\n");
1820 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
1821 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
1822 PFDI_INT(hfdi)->perf->fError = TRUE;
1823 SetLastError(ERROR_FILE_NOT_FOUND);
1824 return FALSE;
1827 /* paste the path and filename together */
1828 idx = 0;
1829 if (pathlen) {
1830 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
1831 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
1833 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
1834 fullpath[idx] = '\0';
1836 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
1838 /* get a handle to the cabfile */
1839 cabhf = PFDI_OPEN(hfdi, fullpath, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
1840 if (cabhf == -1) {
1841 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
1842 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
1843 PFDI_INT(hfdi)->perf->fError = TRUE;
1844 SetLastError(ERROR_FILE_NOT_FOUND);
1845 return FALSE;
1848 /* check if it's really a cabfile. Note that this doesn't implement the bug */
1849 if (!FDI_read_entries(hfdi, cabhf, &fdici, &mii)) {
1850 ERR("FDIIsCabinet failed.\n");
1851 PFDI_CLOSE(hfdi, cabhf);
1852 return FALSE;
1855 /* cabinet notification */
1856 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1857 fdin.setID = fdici.setID;
1858 fdin.iCabinet = fdici.iCabinet;
1859 fdin.pv = pvUser;
1860 fdin.psz1 = (mii.nextname) ? mii.nextname : &emptystring;
1861 fdin.psz2 = (mii.nextinfo) ? mii.nextinfo : &emptystring;
1862 fdin.psz3 = pszCabPath;
1864 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
1865 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
1866 PFDI_INT(hfdi)->perf->erfType = 0;
1867 PFDI_INT(hfdi)->perf->fError = TRUE;
1868 goto bail_and_fail;
1871 /* read folders */
1872 for (i = 0; i < fdici.cFolders; i++) {
1873 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
1874 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
1875 PFDI_INT(hfdi)->perf->erfType = 0;
1876 PFDI_INT(hfdi)->perf->fError = TRUE;
1877 goto bail_and_fail;
1880 if (mii.folder_resv > 0)
1881 PFDI_SEEK(hfdi, cabhf, mii.folder_resv, SEEK_CUR);
1883 fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
1884 if (!fol) {
1885 ERR("out of memory!\n");
1886 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
1887 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
1888 PFDI_INT(hfdi)->perf->fError = TRUE;
1889 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1890 goto bail_and_fail;
1892 ZeroMemory(fol, sizeof(struct fdi_folder));
1893 if (!CAB(firstfol)) CAB(firstfol) = fol;
1895 fol->offset[0] = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
1896 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
1897 fol->comp_type = EndGetI16(buf+cffold_CompType);
1899 if (linkfol)
1900 linkfol->next = fol;
1901 linkfol = fol;
1904 /* read files */
1905 for (i = 0; i < fdici.cFiles; i++) {
1906 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
1907 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
1908 PFDI_INT(hfdi)->perf->erfType = 0;
1909 PFDI_INT(hfdi)->perf->fError = TRUE;
1910 goto bail_and_fail;
1913 file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
1914 if (!file) {
1915 ERR("out of memory!\n");
1916 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
1917 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
1918 PFDI_INT(hfdi)->perf->fError = TRUE;
1919 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1920 goto bail_and_fail;
1922 ZeroMemory(file, sizeof(struct fdi_file));
1923 if (!CAB(firstfile)) CAB(firstfile) = file;
1925 file->length = EndGetI32(buf+cffile_UncompressedSize);
1926 file->offset = EndGetI32(buf+cffile_FolderOffset);
1927 file->index = EndGetI16(buf+cffile_FolderIndex);
1928 file->time = EndGetI16(buf+cffile_Time);
1929 file->date = EndGetI16(buf+cffile_Date);
1930 file->attribs = EndGetI16(buf+cffile_Attribs);
1931 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
1933 if (!file->filename) {
1934 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
1935 PFDI_INT(hfdi)->perf->erfType = 0;
1936 PFDI_INT(hfdi)->perf->fError = TRUE;
1937 goto bail_and_fail;
1940 if (linkfile)
1941 linkfile->next = file;
1942 linkfile = file;
1945 for (file = CAB(firstfile); (file); file = file->next) {
1946 /* partial file notification (do it just once for the first cabinet) */
1947 if (initialcab && ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV)) {
1948 /* OK, more MS bugs to simulate here, I think. I don't have a huge spanning
1949 * cabinet to test this theory on ATM, but here's the deal. The SDK says that we
1950 * are supposed to notify the user of the filename and "disk name" (info) of
1951 * the cabinet where the spanning file /started/. That would certainly be convenient
1952 * for the consumer, who could decide to abort everything and try to start over with
1953 * that cabinet so as not to create a front-truncated output file. Note that this
1954 * task would be a horrible bitch from the implementor's (wine's) perspective: the
1955 * information is associated nowhere with the file header and is not to be found in
1956 * the cabinet header. So we would have to open the previous cabinet, and check
1957 * if it contains a single spanning file that's continued from yet another prior cabinet,
1958 * and so-on, until we find the beginning. Note that cabextract.c has code to do exactly
1959 * this. Luckily, MS clearly didn't implement this logic, so we don't have to either.
1960 * Watching the callbacks (and debugmsg +file) clearly shows that they don't open
1961 * the preceeding cabinet -- and therefore, I deduce, there is NO WAY they could
1962 * have implemented what's in the spec. Instead, they are obviously just returning
1963 * the previous cabinet and it's info from the header of this cabinet. So we shall
1964 * do the same. Of course, I could be missing something...
1966 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1967 fdin.pv = pvUser;
1968 fdin.psz1 = (char *)file->filename;
1969 fdin.psz2 = (mii.prevname) ? mii.prevname : &emptystring;
1970 fdin.psz3 = (mii.previnfo) ? mii.previnfo : &emptystring;
1972 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
1973 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
1974 PFDI_INT(hfdi)->perf->erfType = 0;
1975 PFDI_INT(hfdi)->perf->fError = TRUE;
1976 goto bail_and_fail;
1978 /* I don't think we are supposed to decompress partial files */
1979 file->oppressed = TRUE;
1981 if (file->oppressed) {
1982 filehf = 0;
1983 } else {
1984 /* fdintCOPY_FILE notification (TODO: skip for spanning cab's we already should have hf) */
1985 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1986 fdin.pv = pvUser;
1987 fdin.psz1 = (char *)file->filename;
1988 fdin.cb = file->length;
1989 fdin.date = file->date;
1990 fdin.time = file->time;
1991 fdin.attribs = file->attribs;
1992 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
1993 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
1994 PFDI_INT(hfdi)->perf->erfType = 0;
1995 PFDI_INT(hfdi)->perf->fError = TRUE;
1996 goto bail_and_fail;
2000 if (filehf) {
2001 cab_UWORD comptype = fol->comp_type;
2002 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2003 int err = 0;
2005 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2007 /* set up decomp_state (unneccesary?); at least
2008 ignore trailing three pointers in the struct */
2009 ZeroMemory(decomp_state, sizeof(fdi_decomp_state) - sizeof(void*) * 3);
2010 CAB(hfdi) = hfdi;
2011 CAB(filehf) = filehf;
2012 CAB(cabhf) = cabhf;
2013 CAB(current) = file->folder;
2014 CAB(block_resv) = mii.block_resv;
2016 /* set up the appropriate decompressor */
2017 switch (ct1) {
2018 case cffoldCOMPTYPE_NONE:
2019 CAB(decompress) = NONEfdi_decomp;
2020 break;
2021 case cffoldCOMPTYPE_MSZIP:
2022 CAB(decompress) = ZIPfdi_decomp;
2023 break;
2024 case cffoldCOMPTYPE_QUANTUM:
2025 CAB(decompress) = QTMfdi_decomp;
2026 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2027 break;
2028 case cffoldCOMPTYPE_LZX:
2029 CAB(decompress) = LZXfdi_decomp;
2030 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2031 break;
2032 default:
2033 err = DECR_DATAFORMAT;
2036 switch (err) {
2037 case DECR_OK:
2038 break;
2039 case DECR_NOMEMORY:
2040 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2041 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2042 PFDI_INT(hfdi)->perf->fError = TRUE;
2043 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2044 goto bail_and_fail;
2045 default:
2046 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2047 PFDI_INT(hfdi)->perf->erfOper = 0;
2048 PFDI_INT(hfdi)->perf->fError = TRUE;
2049 goto bail_and_fail;
2052 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset[0], SEEK_SET);
2053 CAB(offset) = 0;
2054 CAB(outlen) = 0;
2055 CAB(split) = 0;
2057 if (file->offset > CAB(offset)) {
2058 /* decode bytes and send them to /dev/null */
2059 switch ((err = fdi_decomp(file, 0, decomp_state))) {
2060 case DECR_OK:
2061 break;
2062 case DECR_NOMEMORY:
2063 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2064 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2065 PFDI_INT(hfdi)->perf->fError = TRUE;
2066 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2067 goto bail_and_fail;
2068 default:
2069 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2070 PFDI_INT(hfdi)->perf->erfOper = 0;
2071 PFDI_INT(hfdi)->perf->fError = TRUE;
2072 goto bail_and_fail;
2074 CAB(offset) = file->offset;
2077 /* now do the actual decompression */
2078 err = fdi_decomp(file, 1, decomp_state);
2079 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2081 switch (err) {
2082 case DECR_OK:
2083 break;
2084 case DECR_NOMEMORY:
2085 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2086 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2087 PFDI_INT(hfdi)->perf->fError = TRUE;
2088 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2089 goto bail_and_fail;
2090 default:
2091 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2092 PFDI_INT(hfdi)->perf->erfOper = 0;
2093 PFDI_INT(hfdi)->perf->fError = TRUE;
2094 goto bail_and_fail;
2097 /* fdintCLOSE_FILE_INFO notification */
2098 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2099 fdin.pv = pvUser;
2100 fdin.psz1 = (char *)file->filename;
2101 fdin.hf = filehf;
2102 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE;
2103 fdin.date = file->date;
2104 fdin.time = file->time;
2105 fdin.attribs = file->attribs;
2106 err = ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2107 if (err == FALSE || err == -1) {
2109 * SDK states that even though they indicated failure,
2110 * we are not supposed to try and close the file, so we
2111 * just treat this like all the others
2113 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2114 PFDI_INT(hfdi)->perf->erfType = 0;
2115 PFDI_INT(hfdi)->perf->fError = TRUE;
2116 goto bail_and_fail;
2121 while (decomp_state) {
2122 fdi_decomp_state *prev_fds;
2123 while (CAB(firstfol)) {
2124 fol = CAB(firstfol);
2125 CAB(firstfol) = CAB(firstfol)->next;
2126 PFDI_FREE(hfdi, fol);
2128 while (CAB(firstfile)) {
2129 file = CAB(firstfile);
2130 CAB(firstfile) = CAB(firstfile)->next;
2131 PFDI_FREE(hfdi, file);
2133 prev_fds = decomp_state;
2134 decomp_state = CAB(next);
2135 if (prev_fds != &_decomp_state)
2136 PFDI_FREE(hfdi, prev_fds);
2139 /* free the storage remembered by mii */
2140 if (mii.nextname) PFDI_FREE(hfdi, mii.nextname);
2141 if (mii.nextinfo) PFDI_FREE(hfdi, mii.nextinfo);
2142 if (mii.prevname) PFDI_FREE(hfdi, mii.prevname);
2143 if (mii.previnfo) PFDI_FREE(hfdi, mii.previnfo);
2145 PFDI_CLOSE(hfdi, cabhf);
2146 return TRUE;
2148 bail_and_fail: /* here we free ram before error returns */
2150 while (decomp_state) {
2151 fdi_decomp_state *prev_fds;
2152 while (CAB(firstfol)) {
2153 fol = CAB(firstfol);
2154 CAB(firstfol) = CAB(firstfol)->next;
2155 PFDI_FREE(hfdi, fol);
2157 while (CAB(firstfile)) {
2158 file = CAB(firstfile);
2159 CAB(firstfile) = CAB(firstfile)->next;
2160 PFDI_FREE(hfdi, file);
2162 prev_fds = decomp_state;
2163 decomp_state = CAB(next);
2164 if (prev_fds != &_decomp_state)
2165 PFDI_FREE(hfdi, prev_fds);
2168 /* free the storage remembered by mii */
2169 if (mii.nextname) PFDI_FREE(hfdi, mii.nextname);
2170 if (mii.nextinfo) PFDI_FREE(hfdi, mii.nextinfo);
2171 if (mii.prevname) PFDI_FREE(hfdi, mii.prevname);
2172 if (mii.previnfo) PFDI_FREE(hfdi, mii.previnfo);
2174 PFDI_CLOSE(hfdi, cabhf);
2175 return FALSE;
2178 /***********************************************************************
2179 * FDIDestroy (CABINET.23)
2181 BOOL __cdecl FDIDestroy(HFDI hfdi)
2183 TRACE("(hfdi == ^%p)\n", hfdi);
2184 if (REALLY_IS_FDI(hfdi)) {
2185 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2186 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2187 return TRUE;
2188 } else {
2189 SetLastError(ERROR_INVALID_HANDLE);
2190 return FALSE;
2194 /***********************************************************************
2195 * FDITruncateCabinet (CABINET.24)
2197 BOOL __cdecl FDITruncateCabinet(
2198 HFDI hfdi,
2199 char *pszCabinetName,
2200 USHORT iFolderToDelete)
2202 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2203 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2205 if (!REALLY_IS_FDI(hfdi)) {
2206 SetLastError(ERROR_INVALID_HANDLE);
2207 return FALSE;
2210 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2211 return FALSE;