- eliminate pesky global variables; should be threadsafe now
[wine] / dlls / cabinet / fdi.c
1 /*
2  * File Decompression Interface
3  *
4  * Copyright 2000-2002 Stuart Caie
5  * Copyright 2002 Patrik Stridvall
6  * Copyright 2003 Greg Turner
7  *
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.
12  *
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.
17  *
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
21  *
22  *
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).  Also,
28  * cabextract's implementation is pretty efficient; fdi.c is, by contrast, extremely
29  * wasteful...
30  *
31  *   -gmt
32  */
33
34 #include "config.h"
35
36 #include <stdio.h>
37
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winerror.h"
41 #include "fdi.h"
42 #include "msvcrt/fcntl.h" /* _O_.* */
43 #include "cabinet.h"
44
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
48
49 THOSE_ZIP_CONSTS;
50
51 struct fdi_file {
52   struct fdi_file *next;               /* next file in sequence          */
53   LPCSTR filename;                     /* output name of file            */
54   int    fh;                           /* open file handle or NULL       */
55   cab_ULONG length;                    /* uncompressed length of file    */
56   cab_ULONG offset;                    /* uncompressed offset in folder  */
57   cab_UWORD index;                     /* magic index number of folder   */
58   cab_UWORD time, date, attribs;       /* MS-DOS time/date/attributes    */
59   BOOL oppressed;                       /* never to be processed          */
60 };
61
62 struct fdi_folder {
63   struct fdi_folder *next;
64   cab_off_t offset;                    /* offset to data blocks (32 bit) */
65   cab_UWORD comp_type;                 /* compression format/window size */
66   cab_ULONG comp_size;                 /* compressed size of folder      */
67   cab_UBYTE num_splits;                /* number of split blocks + 1     */
68   cab_UWORD num_blocks;                /* total number of blocks         */
69 };
70
71 /*
72  * this structure fills the gaps between what is available in a PFDICABINETINFO
73  * vs what is needed by FDICopy.  Memory allocated for these becomes the responsibility
74  * of the caller to free.  Yes, I am aware that this is totally, utterly inelegant.
75  * To make things even more unneccesarily confusing, we now attach these to the
76  * fdi_decomp_state.
77  */
78 typedef struct {
79    char *prevname, *previnfo;
80    char *nextname, *nextinfo;
81    BOOL hasnext;  /* bug free indicator */
82    int folder_resv, header_resv;
83    cab_UBYTE block_resv;
84 } MORE_ISCAB_INFO, *PMORE_ISCAB_INFO;
85
86 /*
87  * ugh, well, this ended up being pretty damn silly...
88  * now that I've conceeded to build equivalent structures to struct cab.*,
89  * I should have just used those, or, better yet, unified the two... sue me.
90  * (Note to Microsoft: That's a joke.  Please /don't/ actually sue me! -gmt).
91  * Nevertheless, I've come this far, it works, so I'm not gonna change it
92  * for now.  This implementation has significant semantic differences anyhow.
93  */
94
95 typedef struct fdi_cds_fwd {
96   void *hfdi;                      /* the hfdi we are using                 */
97   int filehf, cabhf;               /* file handle we are using              */
98   struct fdi_folder *current;      /* current folder we're extracting from  */
99   cab_ULONG offset;                /* uncompressed offset within folder     */
100   cab_UBYTE *outpos;               /* (high level) start of data to use up  */
101   cab_UWORD outlen;                /* (high level) amount of data to use up */
102   int (*decompress)(int, int, struct fdi_cds_fwd *); /* chosen compress fn  */
103   cab_UBYTE inbuf[CAB_INPUTMAX+2]; /* +2 for lzx bitbuffer overflows!       */
104   cab_UBYTE outbuf[CAB_BLOCKMAX];
105   union {
106     struct ZIPstate zip;
107     struct QTMstate qtm;
108     struct LZXstate lzx;
109   } methods;
110   /* some temp variables for use during decompression */
111   cab_UBYTE q_length_base[27], q_length_extra[27], q_extra_bits[42];
112   cab_ULONG q_position_base[42];
113   cab_ULONG lzx_position_base[51];
114   cab_UBYTE extra_bits[51];
115   USHORT  setID;                   /* Cabinet set ID */
116   USHORT  iCabinet;                /* Cabinet number in set (0 based) */
117   struct fdi_cds_fwd *decomp_cab;
118   MORE_ISCAB_INFO mii;
119   struct fdi_folder *firstfol; 
120   struct fdi_file   *firstfile;
121   struct fdi_cds_fwd *next;
122 } fdi_decomp_state;
123
124 /***********************************************************************
125  *              FDICreate (CABINET.20)
126  */
127 HFDI __cdecl FDICreate(
128         PFNALLOC pfnalloc,
129         PFNFREE  pfnfree,
130         PFNOPEN  pfnopen,
131         PFNREAD  pfnread,
132         PFNWRITE pfnwrite,
133         PFNCLOSE pfnclose,
134         PFNSEEK  pfnseek,
135         int      cpuType,
136         PERF     perf)
137 {
138   HFDI rv;
139
140   TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, \
141         pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n", 
142         pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
143         cpuType, perf);
144
145   if ((!pfnalloc) || (!pfnfree)) {
146     perf->erfOper = FDIERROR_NONE;
147     perf->erfType = ERROR_BAD_ARGUMENTS;
148     perf->fError = TRUE;
149
150     SetLastError(ERROR_BAD_ARGUMENTS);
151     return NULL;
152   }
153
154   if (!((rv = ((HFDI) (*pfnalloc)(sizeof(FDI_Int)))))) {
155     perf->erfOper = FDIERROR_ALLOC_FAIL;
156     perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
157     perf->fError = TRUE;
158
159     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
160     return NULL;
161   }
162   
163   PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
164   PFDI_INT(rv)->pfnalloc = pfnalloc;
165   PFDI_INT(rv)->pfnfree = pfnfree;
166   PFDI_INT(rv)->pfnopen = pfnopen;
167   PFDI_INT(rv)->pfnread = pfnread;
168   PFDI_INT(rv)->pfnwrite = pfnwrite;
169   PFDI_INT(rv)->pfnclose = pfnclose;
170   PFDI_INT(rv)->pfnseek = pfnseek;
171   /* no-brainer: we ignore the cpu type; this is only used
172      for the 16-bit versions in Windows anyhow... */
173   PFDI_INT(rv)->perf = perf;
174
175   return rv;
176 }
177
178 /*******************************************************************
179  * FDI_getoffset (internal)
180  *
181  * returns the file pointer position of a cab
182  */
183 long FDI_getoffset(HFDI hfdi, INT_PTR hf)
184 {
185   return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
186 }
187
188 /**********************************************************************
189  * FDI_realloc (internal)
190  *
191  * we can't use _msize; the user might not be using malloc, so we require
192  * an explicit specification of the previous size. utterly inefficient.
193  */
194 void *FDI_realloc(HFDI hfdi, void *mem, size_t prevsize, size_t newsize)
195 {
196   void *rslt = NULL;
197   char *irslt, *imem;
198   size_t copysize = (prevsize < newsize) ? prevsize : newsize;
199   if (prevsize == newsize) return mem;
200   rslt = PFDI_ALLOC(hfdi, newsize); 
201   if (rslt)
202     for (irslt = (char *)rslt, imem = (char *)mem; (copysize); copysize--)
203       *irslt++ = *imem++;
204   PFDI_FREE(hfdi, mem);
205   return rslt;
206 }
207
208 /**********************************************************************
209  * FDI_read_string (internal)
210  *
211  * allocate and read an aribitrarily long string from the cabinet
212  */
213 char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
214 {
215   size_t len=256,
216          oldlen = 0,
217          base = FDI_getoffset(hfdi, hf),
218          maxlen = cabsize - base;
219   BOOL ok = FALSE;
220   int i;
221   cab_UBYTE *buf = NULL;
222
223   TRACE("(hfdi == ^%p, hf == %d)\n", hfdi, hf);
224
225   do {
226     if (len > maxlen) len = maxlen;
227     if (!(buf = FDI_realloc(hfdi, buf, oldlen, len))) break;
228     oldlen = len;
229     if (!PFDI_READ(hfdi, hf, buf, len)) break;
230
231     /* search for a null terminator in what we've just read */
232     for (i=0; i < len; i++) {
233       if (!buf[i]) {ok=TRUE; break;}
234     }
235
236     if (!ok) {
237       if (len == maxlen) {
238         ERR("WARNING: cabinet is truncated\n");
239         break;
240       }
241       len += 256;
242       PFDI_SEEK(hfdi, hf, base, SEEK_SET);
243     }
244   } while (!ok);
245
246   if (!ok) {
247     if (buf)
248       PFDI_FREE(hfdi, buf);
249     else
250       ERR("out of memory!\n");
251     return NULL;
252   }
253
254   /* otherwise, set the stream to just after the string and return */
255   PFDI_SEEK(hfdi, hf, base + ((cab_off_t) strlen((char *) buf)) + 1, SEEK_SET);
256
257   return (char *) buf;
258 }
259
260 /******************************************************************
261  * FDI_read_entries (internal)
262  *
263  * process the cabinet header in the style of FDIIsCabinet, but
264  * without the sanity checks (and bug)
265  *
266  */
267 BOOL FDI_read_entries(
268         HFDI             hfdi,
269         INT_PTR          hf,
270         PFDICABINETINFO  pfdici,
271         PMORE_ISCAB_INFO pmii)
272 {
273   int num_folders, num_files, header_resv, folder_resv = 0;
274   LONG base_offset, cabsize;
275   USHORT setid, cabidx, flags;
276   cab_UBYTE buf[64], block_resv;
277   char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
278
279   TRACE("(hfdi == ^%p, hf == %d, pfdici == ^%p)\n", hfdi, hf, pfdici);
280
281   /* get basic offset & size info */
282   base_offset = FDI_getoffset(hfdi, hf);
283
284   if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
285     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
286     PFDI_INT(hfdi)->perf->erfType = 0;
287     PFDI_INT(hfdi)->perf->fError = TRUE;
288     return FALSE;
289   }
290
291   cabsize = FDI_getoffset(hfdi, hf);
292
293   if ((cabsize == -1) || (base_offset == -1) || 
294       ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
295     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
296     PFDI_INT(hfdi)->perf->erfType = 0;
297     PFDI_INT(hfdi)->perf->fError = TRUE;
298     return FALSE;
299   }
300
301   /* read in the CFHEADER */
302   if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
303     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
304     PFDI_INT(hfdi)->perf->erfType = 0;
305     PFDI_INT(hfdi)->perf->fError = TRUE;
306     return FALSE;
307   }
308   
309   /* check basic MSCF signature */
310   if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
311     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
312     PFDI_INT(hfdi)->perf->erfType = 0;
313     PFDI_INT(hfdi)->perf->fError = TRUE;
314     return FALSE;
315   }
316
317   /* get the number of folders */
318   num_folders = EndGetI16(buf+cfhead_NumFolders);
319   if (num_folders == 0) {
320     /* PONDERME: is this really invalid? */
321     WARN("weird cabinet detect failure: no folders in cabinet\n");
322     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
323     PFDI_INT(hfdi)->perf->erfType = 0;
324     PFDI_INT(hfdi)->perf->fError = TRUE;
325     return FALSE;
326   }
327
328   /* get the number of files */
329   num_files = EndGetI16(buf+cfhead_NumFiles);
330   if (num_files == 0) {
331     /* PONDERME: is this really invalid? */
332     WARN("weird cabinet detect failure: no files in cabinet\n");
333     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
334     PFDI_INT(hfdi)->perf->erfType = 0;
335     PFDI_INT(hfdi)->perf->fError = TRUE;
336     return FALSE;
337   }
338
339   /* setid */
340   setid = EndGetI16(buf+cfhead_SetID);
341
342   /* cabinet (set) index */
343   cabidx = EndGetI16(buf+cfhead_CabinetIndex);
344
345   /* check the header revision */
346   if ((buf[cfhead_MajorVersion] > 1) ||
347       (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
348   {
349     WARN("cabinet format version > 1.3\n");
350     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
351     PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
352     PFDI_INT(hfdi)->perf->fError = TRUE;
353     return FALSE;
354   }
355
356   /* pull the flags out */
357   flags = EndGetI16(buf+cfhead_Flags);
358
359   /* read the reserved-sizes part of header, if present */
360   if (flags & cfheadRESERVE_PRESENT) {
361     if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
362       ERR("bunk reserve-sizes?\n");
363       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
364       PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
365       PFDI_INT(hfdi)->perf->fError = TRUE;
366       return FALSE;
367     }
368
369     header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
370     if (pmii) pmii->header_resv = header_resv;
371     folder_resv = buf[cfheadext_FolderReserved];
372     if (pmii) pmii->folder_resv = folder_resv;
373     block_resv  = buf[cfheadext_DataReserved];
374     if (pmii) pmii->block_resv = block_resv;
375
376     if (header_resv > 60000) {
377       WARN("WARNING; header reserved space > 60000\n");
378     }
379
380     /* skip the reserved header */
381     if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
382       ERR("seek failure: header_resv\n");
383       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
384       PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
385       PFDI_INT(hfdi)->perf->fError = TRUE;
386       return FALSE;
387     }
388   }
389
390   if (flags & cfheadPREV_CABINET) {
391     prevname = FDI_read_string(hfdi, hf, cabsize);
392     if (!prevname) {
393       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
394       PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
395       PFDI_INT(hfdi)->perf->fError = TRUE;
396       return FALSE;
397     } else
398       if (pmii)
399         pmii->prevname = prevname;
400       else
401         PFDI_FREE(hfdi, prevname);
402     previnfo = FDI_read_string(hfdi, hf, cabsize);
403     if (previnfo) {
404       if (pmii) 
405         pmii->previnfo = previnfo;
406       else
407         PFDI_FREE(hfdi, previnfo);
408     }
409   }
410
411   if (flags & cfheadNEXT_CABINET) {
412     if (pmii)
413       pmii->hasnext = TRUE;
414     nextname = FDI_read_string(hfdi, hf, cabsize);
415     if (!nextname) {
416       if ((flags & cfheadPREV_CABINET) && pmii) {
417         if (pmii->prevname) PFDI_FREE(hfdi, prevname);
418         if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
419       }
420       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
421       PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
422       PFDI_INT(hfdi)->perf->fError = TRUE;
423       return FALSE;
424     } else
425       if (pmii)
426         pmii->nextname = nextname;
427       else
428         PFDI_FREE(hfdi, nextname);
429     nextinfo = FDI_read_string(hfdi, hf, cabsize);
430     if (nextinfo) {
431       if (pmii)
432         pmii->nextinfo = nextinfo;
433       else
434         PFDI_FREE(hfdi, nextinfo);
435     }
436   }
437
438   /* we could process the whole cabinet searching for problems;
439      instead lets stop here.  Now let's fill out the paperwork */
440   pfdici->cbCabinet = cabsize;
441   pfdici->cFolders  = num_folders;
442   pfdici->cFiles    = num_files;
443   pfdici->setID     = setid;
444   pfdici->iCabinet  = cabidx;
445   pfdici->fReserve  = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
446   pfdici->hasprev   = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
447   pfdici->hasnext   = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
448   return TRUE;
449 }
450
451 /***********************************************************************
452  *              FDIIsCabinet (CABINET.21)
453  */
454 BOOL __cdecl FDIIsCabinet(
455         HFDI            hfdi,
456         INT_PTR         hf,
457         PFDICABINETINFO pfdici)
458 {
459   BOOL rv;
460
461   TRACE("(hfdi == ^%p, hf == ^%d, pfdici == ^%p)\n", hfdi, hf, pfdici);
462
463   if (!REALLY_IS_FDI(hfdi)) {
464     ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
465     SetLastError(ERROR_INVALID_HANDLE);
466     return FALSE;
467   }
468
469   if (!hf) {
470     ERR("(!hf)!\n");
471     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
472     PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
473     PFDI_INT(hfdi)->perf->fError = TRUE;
474     SetLastError(ERROR_INVALID_HANDLE);
475     return FALSE;
476   }
477
478   if (!pfdici) {
479     ERR("(!pfdici)!\n");
480     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
481     PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
482     PFDI_INT(hfdi)->perf->fError = TRUE;
483     SetLastError(ERROR_BAD_ARGUMENTS);
484     return FALSE;
485   }
486   rv = FDI_read_entries(hfdi, hf, pfdici, NULL); 
487
488   if (rv)
489     pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
490
491   return rv;
492 }
493
494 /******************************************************************
495  * QTMfdi_initmodel (internal)
496  *
497  * Initialise a model which decodes symbols from [s] to [s]+[n]-1
498  */
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 */
509   }
510   m->syms[n].cumfreq = 0;
511 }
512
513 /******************************************************************
514  * QTMfdi_init (internal)
515  */
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;
519
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;
526   }
527   if (!QTM(window)) {
528     if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
529     QTM(actual_size) = wndsize;
530   }
531   QTM(window_size) = wndsize;
532   QTM(window_posn) = 0;
533
534   /* initialise static slot/extrabits tables */
535   for (i = 0, j = 0; i < 27; i++) {
536     CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
537     CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
538   }
539   for (i = 0, j = 0; i < 42; i++) {
540     CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
541     CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
542   }
543
544   /* initialise arithmetic coding models */
545
546   QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
547
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);
552
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);
560
561   return DECR_OK;
562 }
563
564 /************************************************************
565  * LZXfdi_init (internal)
566  */
567 int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
568   cab_ULONG wndsize = 1 << window;
569   int i, j, posn_slots;
570
571   /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
572   /* if a previously allocated window is big enough, keep it     */
573   if (window < 15 || window > 21) return DECR_DATAFORMAT;
574   if (LZX(actual_size) < wndsize) {
575     if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
576     LZX(window) = NULL;
577   }
578   if (!LZX(window)) {
579     if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
580     LZX(actual_size) = wndsize;
581   }
582   LZX(window_size) = wndsize;
583
584   /* initialise static tables */
585   for (i=0, j=0; i <= 50; i += 2) {
586     CAB(extra_bits)[i] = CAB(extra_bits)[i+1] = j; /* 0,0,0,0,1,1,2,2,3,3... */
587     if ((i != 0) && (j < 17)) j++; /* 0,0,1,2,3,4...15,16,17,17,17,17... */
588   }
589   for (i=0, j=0; i <= 50; i++) {
590     CAB(lzx_position_base)[i] = j; /* 0,1,2,3,4,6,8,12,16,24,32,... */
591     j += 1 << CAB(extra_bits)[i]; /* 1,1,1,1,2,2,4,4,8,8,16,16,32,32,... */
592   }
593
594   /* calculate required position slots */
595        if (window == 20) posn_slots = 42;
596   else if (window == 21) posn_slots = 50;
597   else posn_slots = window << 1;
598
599   /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
600
601   LZX(R0)  =  LZX(R1)  = LZX(R2) = 1;
602   LZX(main_elements)   = LZX_NUM_CHARS + (posn_slots << 3);
603   LZX(header_read)     = 0;
604   LZX(frames_read)     = 0;
605   LZX(block_remaining) = 0;
606   LZX(block_type)      = LZX_BLOCKTYPE_INVALID;
607   LZX(intel_curpos)    = 0;
608   LZX(intel_started)   = 0;
609   LZX(window_posn)     = 0;
610
611   /* initialise tables to 0 (because deltas will be applied to them) */
612   for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) LZX(MAINTREE_len)[i] = 0;
613   for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++)   LZX(LENGTH_len)[i]   = 0;
614
615   return DECR_OK;
616 }
617
618 /****************************************************
619  * NONEfdi_decomp(internal)
620  */
621 int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
622 {
623   if (inlen != outlen) return DECR_ILLEGALDATA;
624   memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
625   return DECR_OK;
626 }
627
628 /********************************************************
629  * Ziphuft_free (internal)
630  */
631 void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
632 {
633   register struct Ziphuft *p, *q;
634
635   /* Go through linked list, freeing from the allocated (t[-1]) address. */
636   p = t;
637   while (p != (struct Ziphuft *)NULL)
638   {
639     q = (--p)->v.t;
640     PFDI_FREE(hfdi, p);
641     p = q;
642   } 
643 }
644
645 /*********************************************************
646  * fdi_Ziphuft_build (internal)
647  */
648 cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, cab_UWORD *d, cab_UWORD *e,
649 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
650 {
651   cab_ULONG a;                          /* counter for codes of length k */
652   cab_ULONG el;                         /* length of EOB code (value 256) */
653   cab_ULONG f;                          /* i repeats in table every f entries */
654   cab_LONG g;                           /* maximum code length */
655   cab_LONG h;                           /* table level */
656   register cab_ULONG i;                 /* counter, current code */
657   register cab_ULONG j;                 /* counter */
658   register cab_LONG k;                  /* number of bits in current code */
659   cab_LONG *l;                          /* stack of bits per table */
660   register cab_ULONG *p;                /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
661   register struct Ziphuft *q;           /* points to current table */
662   struct Ziphuft r;                     /* table entry for structure assignment */
663   register cab_LONG w;                  /* bits before this table == (l * h) */
664   cab_ULONG *xp;                        /* pointer into x */
665   cab_LONG y;                           /* number of dummy codes added */
666   cab_ULONG z;                          /* number of entries in current table */
667
668   l = ZIP(lx)+1;
669
670   /* Generate counts for each bit length */
671   el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
672
673   for(i = 0; i < ZIPBMAX+1; ++i)
674     ZIP(c)[i] = 0;
675   p = b;  i = n;
676   do
677   {
678     ZIP(c)[*p]++; p++;               /* assume all entries <= ZIPBMAX */
679   } while (--i);
680   if (ZIP(c)[0] == n)                /* null input--all zero length codes */
681   {
682     *t = (struct Ziphuft *)NULL;
683     *m = 0;
684     return 0;
685   }
686
687   /* Find minimum and maximum length, bound *m by those */
688   for (j = 1; j <= ZIPBMAX; j++)
689     if (ZIP(c)[j])
690       break;
691   k = j;                        /* minimum code length */
692   if ((cab_ULONG)*m < j)
693     *m = j;
694   for (i = ZIPBMAX; i; i--)
695     if (ZIP(c)[i])
696       break;
697   g = i;                        /* maximum code length */
698   if ((cab_ULONG)*m > i)
699     *m = i;
700
701   /* Adjust last length count to fill out codes, if needed */
702   for (y = 1 << j; j < i; j++, y <<= 1)
703     if ((y -= ZIP(c)[j]) < 0)
704       return 2;                 /* bad input: more codes than bits */
705   if ((y -= ZIP(c)[i]) < 0)
706     return 2;
707   ZIP(c)[i] += y;
708
709   /* Generate starting offsets LONGo the value table for each length */
710   ZIP(x)[1] = j = 0;
711   p = ZIP(c) + 1;  xp = ZIP(x) + 2;
712   while (--i)
713   {                 /* note that i == g from above */
714     *xp++ = (j += *p++);
715   }
716
717   /* Make a table of values in order of bit lengths */
718   p = b;  i = 0;
719   do{
720     if ((j = *p++) != 0)
721       ZIP(v)[ZIP(x)[j]++] = i;
722   } while (++i < n);
723
724
725   /* Generate the Huffman codes and for each, make the table entries */
726   ZIP(x)[0] = i = 0;                 /* first Huffman code is zero */
727   p = ZIP(v);                        /* grab values in bit order */
728   h = -1;                       /* no tables yet--level -1 */
729   w = l[-1] = 0;                /* no bits decoded yet */
730   ZIP(u)[0] = (struct Ziphuft *)NULL;   /* just to keep compilers happy */
731   q = (struct Ziphuft *)NULL;      /* ditto */
732   z = 0;                        /* ditto */
733
734   /* go through the bit lengths (k already is bits in shortest code) */
735   for (; k <= g; k++)
736   {
737     a = ZIP(c)[k];
738     while (a--)
739     {
740       /* here i is the Huffman code of length k bits for value *p */
741       /* make tables up to required level */
742       while (k > w + l[h])
743       {
744         w += l[h++];            /* add bits already decoded */
745
746         /* compute minimum size table less than or equal to *m bits */
747         z = (z = g - w) > (cab_ULONG)*m ? *m : z;        /* upper limit */
748         if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
749         {                       /* too few codes for k-w bit table */
750           f -= a + 1;           /* deduct codes from patterns left */
751           xp = ZIP(c) + k;
752           while (++j < z)       /* try smaller tables up to z bits */
753           {
754             if ((f <<= 1) <= *++xp)
755               break;            /* enough codes to use up j bits */
756             f -= *xp;           /* else deduct codes from patterns */
757           }
758         }
759         if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
760           j = el - w;           /* make EOB code end at table */
761         z = 1 << j;             /* table entries for j-bit table */
762         l[h] = j;               /* set table size in stack */
763
764         /* allocate and link in new table */
765         if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
766         {
767           if(h)
768             fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
769           return 3;             /* not enough memory */
770         }
771         *t = q + 1;             /* link to list for Ziphuft_free() */
772         *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
773         ZIP(u)[h] = ++q;             /* table starts after link */
774
775         /* connect to last table, if there is one */
776         if (h)
777         {
778           ZIP(x)[h] = i;              /* save pattern for backing up */
779           r.b = (cab_UBYTE)l[h-1];    /* bits to dump before this table */
780           r.e = (cab_UBYTE)(16 + j);  /* bits in this table */
781           r.v.t = q;                  /* pointer to this table */
782           j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
783           ZIP(u)[h-1][j] = r;        /* connect to last table */
784         }
785       }
786
787       /* set up table entry in r */
788       r.b = (cab_UBYTE)(k - w);
789       if (p >= ZIP(v) + n)
790         r.e = 99;               /* out of values--invalid code */
791       else if (*p < s)
792       {
793         r.e = (cab_UBYTE)(*p < 256 ? 16 : 15);    /* 256 is end-of-block code */
794         r.v.n = *p++;           /* simple code is just the value */
795       }
796       else
797       {
798         r.e = (cab_UBYTE)e[*p - s];   /* non-simple--look up in lists */
799         r.v.n = d[*p++ - s];
800       }
801
802       /* fill code-like entries with r */
803       f = 1 << (k - w);
804       for (j = i >> w; j < z; j += f)
805         q[j] = r;
806
807       /* backwards increment the k-bit code i */
808       for (j = 1 << (k - 1); i & j; j >>= 1)
809         i ^= j;
810       i ^= j;
811
812       /* backup over finished tables */
813       while ((i & ((1 << w) - 1)) != ZIP(x)[h])
814         w -= l[--h];            /* don't need to update q */
815     }
816   }
817
818   /* return actual size of base table */
819   *m = l[0];
820
821   /* Return true (1) if we were given an incomplete table */
822   return y != 0 && g != 1;
823 }
824
825 /*********************************************************
826  * fdi_Zipinflate_codes (internal)
827  */
828 cab_LONG fdi_Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td,
829   cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
830 {
831   register cab_ULONG e;  /* table entry flag/number of extra bits */
832   cab_ULONG n, d;        /* length and index for copy */
833   cab_ULONG w;           /* current window position */
834   struct Ziphuft *t;     /* pointer to table entry */
835   cab_ULONG ml, md;      /* masks for bl and bd bits */
836   register cab_ULONG b;  /* bit buffer */
837   register cab_ULONG k;  /* number of bits in bit buffer */
838
839   /* make local copies of globals */
840   b = ZIP(bb);                       /* initialize bit buffer */
841   k = ZIP(bk);
842   w = ZIP(window_posn);                       /* initialize window position */
843
844   /* inflate the coded data */
845   ml = Zipmask[bl];             /* precompute masks for speed */
846   md = Zipmask[bd];
847
848   for(;;)
849   {
850     ZIPNEEDBITS((cab_ULONG)bl)
851     if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16)
852       do
853       {
854         if (e == 99)
855           return 1;
856         ZIPDUMPBITS(t->b)
857         e -= 16;
858         ZIPNEEDBITS(e)
859       } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
860     ZIPDUMPBITS(t->b)
861     if (e == 16)                /* then it's a literal */
862       CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
863     else                        /* it's an EOB or a length */
864     {
865       /* exit if end of block */
866       if(e == 15)
867         break;
868
869       /* get length of block to copy */
870       ZIPNEEDBITS(e)
871       n = t->v.n + ((cab_ULONG)b & Zipmask[e]);
872       ZIPDUMPBITS(e);
873
874       /* decode distance of block to copy */
875       ZIPNEEDBITS((cab_ULONG)bd)
876       if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16)
877         do {
878           if (e == 99)
879             return 1;
880           ZIPDUMPBITS(t->b)
881           e -= 16;
882           ZIPNEEDBITS(e)
883         } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
884       ZIPDUMPBITS(t->b)
885       ZIPNEEDBITS(e)
886       d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]);
887       ZIPDUMPBITS(e)
888       do
889       {
890         n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
891         do
892         {
893           CAB(outbuf)[w++] = CAB(outbuf)[d++];
894         } while (--e);
895       } while (n);
896     }
897   }
898
899   /* restore the globals from the locals */
900   ZIP(window_posn) = w;              /* restore global window pointer */
901   ZIP(bb) = b;                       /* restore global bit buffer */
902   ZIP(bk) = k;
903
904   /* done */
905   return 0;
906 }
907
908 /***********************************************************
909  * Zipinflate_stored (internal)
910  */
911 cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
912 /* "decompress" an inflated type 0 (stored) block. */
913 {
914   cab_ULONG n;           /* number of bytes in block */
915   cab_ULONG w;           /* current window position */
916   register cab_ULONG b;  /* bit buffer */
917   register cab_ULONG k;  /* number of bits in bit buffer */
918
919   /* make local copies of globals */
920   b = ZIP(bb);                       /* initialize bit buffer */
921   k = ZIP(bk);
922   w = ZIP(window_posn);              /* initialize window position */
923
924   /* go to byte boundary */
925   n = k & 7;
926   ZIPDUMPBITS(n);
927
928   /* get the length and its complement */
929   ZIPNEEDBITS(16)
930   n = ((cab_ULONG)b & 0xffff);
931   ZIPDUMPBITS(16)
932   ZIPNEEDBITS(16)
933   if (n != (cab_ULONG)((~b) & 0xffff))
934     return 1;                   /* error in compressed data */
935   ZIPDUMPBITS(16)
936
937   /* read and output the compressed data */
938   while(n--)
939   {
940     ZIPNEEDBITS(8)
941     CAB(outbuf)[w++] = (cab_UBYTE)b;
942     ZIPDUMPBITS(8)
943   }
944
945   /* restore the globals from the locals */
946   ZIP(window_posn) = w;              /* restore global window pointer */
947   ZIP(bb) = b;                       /* restore global bit buffer */
948   ZIP(bk) = k;
949   return 0;
950 }
951
952 /******************************************************
953  * fdi_Zipinflate_fixed (internal)
954  */
955 cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
956 {
957   struct Ziphuft *fixed_tl;
958   struct Ziphuft *fixed_td;
959   cab_LONG fixed_bl, fixed_bd;
960   cab_LONG i;                /* temporary variable */
961   cab_ULONG *l;
962
963   l = ZIP(ll);
964
965   /* literal table */
966   for(i = 0; i < 144; i++)
967     l[i] = 8;
968   for(; i < 256; i++)
969     l[i] = 9;
970   for(; i < 280; i++)
971     l[i] = 7;
972   for(; i < 288; i++)          /* make a complete, but wrong code set */
973     l[i] = 8;
974   fixed_bl = 7;
975   if((i = fdi_Ziphuft_build(l, 288, 257, (cab_UWORD *) Zipcplens,
976   (cab_UWORD *) Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
977     return i;
978
979   /* distance table */
980   for(i = 0; i < 30; i++)      /* make an incomplete code set */
981     l[i] = 5;
982   fixed_bd = 5;
983   if((i = fdi_Ziphuft_build(l, 30, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
984   &fixed_td, &fixed_bd, decomp_state)) > 1)
985   {
986     fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
987     return i;
988   }
989
990   /* decompress until an end-of-block code */
991   i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
992
993   fdi_Ziphuft_free(CAB(hfdi), fixed_td);
994   fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
995   return i;
996 }
997
998 /**************************************************************
999  * fdi_Zipinflate_dynamic (internal)
1000  */
1001 cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1002  /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1003 {
1004   cab_LONG i;           /* temporary variables */
1005   cab_ULONG j;
1006   cab_ULONG *ll;
1007   cab_ULONG l;                  /* last length */
1008   cab_ULONG m;                  /* mask for bit lengths table */
1009   cab_ULONG n;                  /* number of lengths to get */
1010   struct Ziphuft *tl;           /* literal/length code table */
1011   struct Ziphuft *td;           /* distance code table */
1012   cab_LONG bl;                  /* lookup bits for tl */
1013   cab_LONG bd;                  /* lookup bits for td */
1014   cab_ULONG nb;                 /* number of bit length codes */
1015   cab_ULONG nl;                 /* number of literal/length codes */
1016   cab_ULONG nd;                 /* number of distance codes */
1017   register cab_ULONG b;         /* bit buffer */
1018   register cab_ULONG k;         /* number of bits in bit buffer */
1019
1020   /* make local bit buffer */
1021   b = ZIP(bb);
1022   k = ZIP(bk);
1023   ll = ZIP(ll);
1024
1025   /* read in table lengths */
1026   ZIPNEEDBITS(5)
1027   nl = 257 + ((cab_ULONG)b & 0x1f);      /* number of literal/length codes */
1028   ZIPDUMPBITS(5)
1029   ZIPNEEDBITS(5)
1030   nd = 1 + ((cab_ULONG)b & 0x1f);        /* number of distance codes */
1031   ZIPDUMPBITS(5)
1032   ZIPNEEDBITS(4)
1033   nb = 4 + ((cab_ULONG)b & 0xf);         /* number of bit length codes */
1034   ZIPDUMPBITS(4)
1035   if(nl > 288 || nd > 32)
1036     return 1;                   /* bad lengths */
1037
1038   /* read in bit-length-code lengths */
1039   for(j = 0; j < nb; j++)
1040   {
1041     ZIPNEEDBITS(3)
1042     ll[Zipborder[j]] = (cab_ULONG)b & 7;
1043     ZIPDUMPBITS(3)
1044   }
1045   for(; j < 19; j++)
1046     ll[Zipborder[j]] = 0;
1047
1048   /* build decoding table for trees--single level, 7 bit lookup */
1049   bl = 7;
1050   if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1051   {
1052     if(i == 1)
1053       fdi_Ziphuft_free(CAB(hfdi), tl);
1054     return i;                   /* incomplete code set */
1055   }
1056
1057   /* read in literal and distance code lengths */
1058   n = nl + nd;
1059   m = Zipmask[bl];
1060   i = l = 0;
1061   while((cab_ULONG)i < n)
1062   {
1063     ZIPNEEDBITS((cab_ULONG)bl)
1064     j = (td = tl + ((cab_ULONG)b & m))->b;
1065     ZIPDUMPBITS(j)
1066     j = td->v.n;
1067     if (j < 16)                 /* length of code in bits (0..15) */
1068       ll[i++] = l = j;          /* save last length in l */
1069     else if (j == 16)           /* repeat last length 3 to 6 times */
1070     {
1071       ZIPNEEDBITS(2)
1072       j = 3 + ((cab_ULONG)b & 3);
1073       ZIPDUMPBITS(2)
1074       if((cab_ULONG)i + j > n)
1075         return 1;
1076       while (j--)
1077         ll[i++] = l;
1078     }
1079     else if (j == 17)           /* 3 to 10 zero length codes */
1080     {
1081       ZIPNEEDBITS(3)
1082       j = 3 + ((cab_ULONG)b & 7);
1083       ZIPDUMPBITS(3)
1084       if ((cab_ULONG)i + j > n)
1085         return 1;
1086       while (j--)
1087         ll[i++] = 0;
1088       l = 0;
1089     }
1090     else                        /* j == 18: 11 to 138 zero length codes */
1091     {
1092       ZIPNEEDBITS(7)
1093       j = 11 + ((cab_ULONG)b & 0x7f);
1094       ZIPDUMPBITS(7)
1095       if ((cab_ULONG)i + j > n)
1096         return 1;
1097       while (j--)
1098         ll[i++] = 0;
1099       l = 0;
1100     }
1101   }
1102
1103   /* free decoding table for trees */
1104   fdi_Ziphuft_free(CAB(hfdi), tl);
1105
1106   /* restore the global bit buffer */
1107   ZIP(bb) = b;
1108   ZIP(bk) = k;
1109
1110   /* build the decoding tables for literal/length and distance codes */
1111   bl = ZIPLBITS;
1112   if((i = fdi_Ziphuft_build(ll, nl, 257, (cab_UWORD *) Zipcplens, (cab_UWORD *) Zipcplext,
1113                         &tl, &bl, decomp_state)) != 0)
1114   {
1115     if(i == 1)
1116       fdi_Ziphuft_free(CAB(hfdi), tl);
1117     return i;                   /* incomplete code set */
1118   }
1119   bd = ZIPDBITS;
1120   fdi_Ziphuft_build(ll + nl, nd, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
1121                 &td, &bd, decomp_state);
1122
1123   /* decompress until an end-of-block code */
1124   if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1125     return 1;
1126
1127   /* free the decoding tables, return */
1128   fdi_Ziphuft_free(CAB(hfdi), tl);
1129   fdi_Ziphuft_free(CAB(hfdi), td);
1130   return 0;
1131 }
1132
1133 /*****************************************************
1134  * fdi_Zipinflate_block (internal)
1135  */
1136 cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1137 { /* decompress an inflated block */
1138   cab_ULONG t;                  /* block type */
1139   register cab_ULONG b;     /* bit buffer */
1140   register cab_ULONG k;     /* number of bits in bit buffer */
1141
1142   /* make local bit buffer */
1143   b = ZIP(bb);
1144   k = ZIP(bk);
1145
1146   /* read in last block bit */
1147   ZIPNEEDBITS(1)
1148   *e = (cab_LONG)b & 1;
1149   ZIPDUMPBITS(1)
1150
1151   /* read in block type */
1152   ZIPNEEDBITS(2)
1153   t = (cab_ULONG)b & 3;
1154   ZIPDUMPBITS(2)
1155
1156   /* restore the global bit buffer */
1157   ZIP(bb) = b;
1158   ZIP(bk) = k;
1159
1160   /* inflate that block type */
1161   if(t == 2)
1162     return fdi_Zipinflate_dynamic(decomp_state);
1163   if(t == 0)
1164     return fdi_Zipinflate_stored(decomp_state);
1165   if(t == 1)
1166     return fdi_Zipinflate_fixed(decomp_state);
1167   /* bad block type */
1168   return 2;
1169 }
1170
1171 /****************************************************
1172  * ZIPfdi_decomp(internal)
1173  */
1174 int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1175 {
1176   cab_LONG e;               /* last block flag */
1177
1178   TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1179
1180   ZIP(inpos) = CAB(inbuf);
1181   ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1182   if(outlen > ZIPWSIZE)
1183     return DECR_DATAFORMAT;
1184
1185   /* CK = Chris Kirmse, official Microsoft purloiner */
1186   if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1187     return DECR_ILLEGALDATA;
1188   ZIP(inpos) += 2;
1189
1190   do {
1191     if(fdi_Zipinflate_block(&e, decomp_state))
1192       return DECR_ILLEGALDATA;
1193   } while(!e);
1194
1195   /* return success */
1196   return DECR_OK;
1197 }
1198
1199 /*******************************************************************
1200  * QTMfdi_decomp(internal)
1201  */
1202 int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1203 {
1204   cab_UBYTE *inpos  = CAB(inbuf);
1205   cab_UBYTE *window = QTM(window);
1206   cab_UBYTE *runsrc, *rundest;
1207
1208   cab_ULONG window_posn = QTM(window_posn);
1209   cab_ULONG window_size = QTM(window_size);
1210
1211   /* used by bitstream macros */
1212   register int bitsleft, bitrun, bitsneed;
1213   register cab_ULONG bitbuf;
1214
1215   /* used by GET_SYMBOL */
1216   cab_ULONG range;
1217   cab_UWORD symf;
1218   int i;
1219
1220   int extra, togo = outlen, match_length = 0, copy_length;
1221   cab_UBYTE selector, sym;
1222   cab_ULONG match_offset = 0;
1223
1224   cab_UWORD H = 0xFFFF, L = 0, C;
1225
1226   TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1227
1228   /* read initial value of C */
1229   Q_INIT_BITSTREAM;
1230   Q_READ_BITS(C, 16);
1231
1232   /* apply 2^x-1 mask */
1233   window_posn &= window_size - 1;
1234   /* runs can't straddle the window wraparound */
1235   if ((window_posn + togo) > window_size) {
1236     TRACE("straddled run\n");
1237     return DECR_DATAFORMAT;
1238   }
1239
1240   while (togo > 0) {
1241     GET_SYMBOL(model7, selector);
1242     switch (selector) {
1243     case 0:
1244       GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1245       break;
1246     case 1:
1247       GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1248       break;
1249     case 2:
1250       GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1251       break;
1252     case 3:
1253       GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1254       break;
1255
1256     case 4:
1257       /* selector 4 = fixed length of 3 */
1258       GET_SYMBOL(model4, sym);
1259       Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1260       match_offset = CAB(q_position_base)[sym] + extra + 1;
1261       match_length = 3;
1262       break;
1263
1264     case 5:
1265       /* selector 5 = fixed length of 4 */
1266       GET_SYMBOL(model5, sym);
1267       Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1268       match_offset = CAB(q_position_base)[sym] + extra + 1;
1269       match_length = 4;
1270       break;
1271
1272     case 6:
1273       /* selector 6 = variable length */
1274       GET_SYMBOL(model6len, sym);
1275       Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1276       match_length = CAB(q_length_base)[sym] + extra + 5;
1277       GET_SYMBOL(model6pos, sym);
1278       Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1279       match_offset = CAB(q_position_base)[sym] + extra + 1;
1280       break;
1281
1282     default:
1283       TRACE("Selector is bogus\n");
1284       return DECR_ILLEGALDATA;
1285     }
1286
1287     /* if this is a match */
1288     if (selector >= 4) {
1289       rundest = window + window_posn;
1290       togo -= match_length;
1291
1292       /* copy any wrapped around source data */
1293       if (window_posn >= match_offset) {
1294         /* no wrap */
1295         runsrc = rundest - match_offset;
1296       } else {
1297         runsrc = rundest + (window_size - match_offset);
1298         copy_length = match_offset - window_posn;
1299         if (copy_length < match_length) {
1300           match_length -= copy_length;
1301           window_posn += copy_length;
1302           while (copy_length-- > 0) *rundest++ = *runsrc++;
1303           runsrc = window;
1304         }
1305       }
1306       window_posn += match_length;
1307
1308       /* copy match data - no worries about destination wraps */
1309       while (match_length-- > 0) *rundest++ = *runsrc++;
1310     }
1311   } /* while (togo > 0) */
1312
1313   if (togo != 0) {
1314     TRACE("Frame overflow, this_run = %d\n", togo);
1315     return DECR_ILLEGALDATA;
1316   }
1317
1318   memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1319     outlen, outlen);
1320
1321   QTM(window_posn) = window_posn;
1322   return DECR_OK;
1323 }
1324
1325 /************************************************************
1326  * fdi_lzx_read_lens (internal)
1327  */
1328 int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1329                   fdi_decomp_state *decomp_state) {
1330   cab_ULONG i,j, x,y;
1331   int z;
1332
1333   register cab_ULONG bitbuf = lb->bb;
1334   register int bitsleft = lb->bl;
1335   cab_UBYTE *inpos = lb->ip;
1336   cab_UWORD *hufftbl;
1337   
1338   for (x = 0; x < 20; x++) {
1339     READ_BITS(y, 4);
1340     LENTABLE(PRETREE)[x] = y;
1341   }
1342   BUILD_TABLE(PRETREE);
1343
1344   for (x = first; x < last; ) {
1345     READ_HUFFSYM(PRETREE, z);
1346     if (z == 17) {
1347       READ_BITS(y, 4); y += 4;
1348       while (y--) lens[x++] = 0;
1349     }
1350     else if (z == 18) {
1351       READ_BITS(y, 5); y += 20;
1352       while (y--) lens[x++] = 0;
1353     }
1354     else if (z == 19) {
1355       READ_BITS(y, 1); y += 4;
1356       READ_HUFFSYM(PRETREE, z);
1357       z = lens[x] - z; if (z < 0) z += 17;
1358       while (y--) lens[x++] = z;
1359     }
1360     else {
1361       z = lens[x] - z; if (z < 0) z += 17;
1362       lens[x++] = z;
1363     }
1364   }
1365
1366   lb->bb = bitbuf;
1367   lb->bl = bitsleft;
1368   lb->ip = inpos;
1369   return 0;
1370 }
1371
1372 /*******************************************************
1373  * LZXfdi_decomp(internal)
1374  */
1375 int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1376   cab_UBYTE *inpos  = CAB(inbuf);
1377   cab_UBYTE *endinp = inpos + inlen;
1378   cab_UBYTE *window = LZX(window);
1379   cab_UBYTE *runsrc, *rundest;
1380   cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1381
1382   cab_ULONG window_posn = LZX(window_posn);
1383   cab_ULONG window_size = LZX(window_size);
1384   cab_ULONG R0 = LZX(R0);
1385   cab_ULONG R1 = LZX(R1);
1386   cab_ULONG R2 = LZX(R2);
1387
1388   register cab_ULONG bitbuf;
1389   register int bitsleft;
1390   cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1391   struct lzx_bits lb; /* used in READ_LENGTHS macro */
1392
1393   int togo = outlen, this_run, main_element, aligned_bits;
1394   int match_length, copy_length, length_footer, extra, verbatim_bits;
1395
1396   TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1397
1398   INIT_BITSTREAM;
1399
1400   /* read header if necessary */
1401   if (!LZX(header_read)) {
1402     i = j = 0;
1403     READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1404     LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1405     LZX(header_read) = 1;
1406   }
1407
1408   /* main decoding loop */
1409   while (togo > 0) {
1410     /* last block finished, new block expected */
1411     if (LZX(block_remaining) == 0) {
1412       if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1413         if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1414         INIT_BITSTREAM;
1415       }
1416
1417       READ_BITS(LZX(block_type), 3);
1418       READ_BITS(i, 16);
1419       READ_BITS(j, 8);
1420       LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1421
1422       switch (LZX(block_type)) {
1423       case LZX_BLOCKTYPE_ALIGNED:
1424         for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1425         BUILD_TABLE(ALIGNED);
1426         /* rest of aligned header is same as verbatim */
1427
1428       case LZX_BLOCKTYPE_VERBATIM:
1429         READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1430         READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1431         BUILD_TABLE(MAINTREE);
1432         if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1433
1434         READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1435         BUILD_TABLE(LENGTH);
1436         break;
1437
1438       case LZX_BLOCKTYPE_UNCOMPRESSED:
1439         LZX(intel_started) = 1; /* because we can't assume otherwise */
1440         ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1441         if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1442         R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1443         R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1444         R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1445         break;
1446
1447       default:
1448         return DECR_ILLEGALDATA;
1449       }
1450     }
1451
1452     /* buffer exhaustion check */
1453     if (inpos > endinp) {
1454       /* it's possible to have a file where the next run is less than
1455        * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1456        * in building the tables will exhaust the buffer, so we should
1457        * allow for this, but not allow those accidentally read bits to
1458        * be used (so we check that there are at least 16 bits
1459        * remaining - in this boundary case they aren't really part of
1460        * the compressed data)
1461        */
1462       if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1463     }
1464
1465     while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1466       if (this_run > togo) this_run = togo;
1467       togo -= this_run;
1468       LZX(block_remaining) -= this_run;
1469
1470       /* apply 2^x-1 mask */
1471       window_posn &= window_size - 1;
1472       /* runs can't straddle the window wraparound */
1473       if ((window_posn + this_run) > window_size)
1474         return DECR_DATAFORMAT;
1475
1476       switch (LZX(block_type)) {
1477
1478       case LZX_BLOCKTYPE_VERBATIM:
1479         while (this_run > 0) {
1480           READ_HUFFSYM(MAINTREE, main_element);
1481
1482           if (main_element < LZX_NUM_CHARS) {
1483             /* literal: 0 to LZX_NUM_CHARS-1 */
1484             window[window_posn++] = main_element;
1485             this_run--;
1486           }
1487           else {
1488             /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1489             main_element -= LZX_NUM_CHARS;
1490   
1491             match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1492             if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1493               READ_HUFFSYM(LENGTH, length_footer);
1494               match_length += length_footer;
1495             }
1496             match_length += LZX_MIN_MATCH;
1497   
1498             match_offset = main_element >> 3;
1499   
1500             if (match_offset > 2) {
1501               /* not repeated offset */
1502               if (match_offset != 3) {
1503                 extra = CAB(extra_bits)[match_offset];
1504                 READ_BITS(verbatim_bits, extra);
1505                 match_offset = CAB(lzx_position_base)[match_offset] 
1506                                - 2 + verbatim_bits;
1507               }
1508               else {
1509                 match_offset = 1;
1510               }
1511   
1512               /* update repeated offset LRU queue */
1513               R2 = R1; R1 = R0; R0 = match_offset;
1514             }
1515             else if (match_offset == 0) {
1516               match_offset = R0;
1517             }
1518             else if (match_offset == 1) {
1519               match_offset = R1;
1520               R1 = R0; R0 = match_offset;
1521             }
1522             else /* match_offset == 2 */ {
1523               match_offset = R2;
1524               R2 = R0; R0 = match_offset;
1525             }
1526
1527             rundest = window + window_posn;
1528             this_run -= match_length;
1529
1530             /* copy any wrapped around source data */
1531             if (window_posn >= match_offset) {
1532               /* no wrap */
1533               runsrc = rundest - match_offset;
1534             } else {
1535               runsrc = rundest + (window_size - match_offset);
1536               copy_length = match_offset - window_posn;
1537               if (copy_length < match_length) {
1538                 match_length -= copy_length;
1539                 window_posn += copy_length;
1540                 while (copy_length-- > 0) *rundest++ = *runsrc++;
1541                 runsrc = window;
1542               }
1543             }
1544             window_posn += match_length;
1545
1546             /* copy match data - no worries about destination wraps */
1547             while (match_length-- > 0) *rundest++ = *runsrc++;
1548           }
1549         }
1550         break;
1551
1552       case LZX_BLOCKTYPE_ALIGNED:
1553         while (this_run > 0) {
1554           READ_HUFFSYM(MAINTREE, main_element);
1555   
1556           if (main_element < LZX_NUM_CHARS) {
1557             /* literal: 0 to LZX_NUM_CHARS-1 */
1558             window[window_posn++] = main_element;
1559             this_run--;
1560           }
1561           else {
1562             /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1563             main_element -= LZX_NUM_CHARS;
1564   
1565             match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1566             if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1567               READ_HUFFSYM(LENGTH, length_footer);
1568               match_length += length_footer;
1569             }
1570             match_length += LZX_MIN_MATCH;
1571   
1572             match_offset = main_element >> 3;
1573   
1574             if (match_offset > 2) {
1575               /* not repeated offset */
1576               extra = CAB(extra_bits)[match_offset];
1577               match_offset = CAB(lzx_position_base)[match_offset] - 2;
1578               if (extra > 3) {
1579                 /* verbatim and aligned bits */
1580                 extra -= 3;
1581                 READ_BITS(verbatim_bits, extra);
1582                 match_offset += (verbatim_bits << 3);
1583                 READ_HUFFSYM(ALIGNED, aligned_bits);
1584                 match_offset += aligned_bits;
1585               }
1586               else if (extra == 3) {
1587                 /* aligned bits only */
1588                 READ_HUFFSYM(ALIGNED, aligned_bits);
1589                 match_offset += aligned_bits;
1590               }
1591               else if (extra > 0) { /* extra==1, extra==2 */
1592                 /* verbatim bits only */
1593                 READ_BITS(verbatim_bits, extra);
1594                 match_offset += verbatim_bits;
1595               }
1596               else /* extra == 0 */ {
1597                 /* ??? */
1598                 match_offset = 1;
1599               }
1600   
1601               /* update repeated offset LRU queue */
1602               R2 = R1; R1 = R0; R0 = match_offset;
1603             }
1604             else if (match_offset == 0) {
1605               match_offset = R0;
1606             }
1607             else if (match_offset == 1) {
1608               match_offset = R1;
1609               R1 = R0; R0 = match_offset;
1610             }
1611             else /* match_offset == 2 */ {
1612               match_offset = R2;
1613               R2 = R0; R0 = match_offset;
1614             }
1615
1616             rundest = window + window_posn;
1617             this_run -= match_length;
1618
1619             /* copy any wrapped around source data */
1620             if (window_posn >= match_offset) {
1621               /* no wrap */
1622               runsrc = rundest - match_offset;
1623             } else {
1624               runsrc = rundest + (window_size - match_offset);
1625               copy_length = match_offset - window_posn;
1626               if (copy_length < match_length) {
1627                 match_length -= copy_length;
1628                 window_posn += copy_length;
1629                 while (copy_length-- > 0) *rundest++ = *runsrc++;
1630                 runsrc = window;
1631               }
1632             }
1633             window_posn += match_length;
1634
1635             /* copy match data - no worries about destination wraps */
1636             while (match_length-- > 0) *rundest++ = *runsrc++;
1637           }
1638         }
1639         break;
1640
1641       case LZX_BLOCKTYPE_UNCOMPRESSED:
1642         if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1643         memcpy(window + window_posn, inpos, (size_t) this_run);
1644         inpos += this_run; window_posn += this_run;
1645         break;
1646
1647       default:
1648         return DECR_ILLEGALDATA; /* might as well */
1649       }
1650
1651     }
1652   }
1653
1654   if (togo != 0) return DECR_ILLEGALDATA;
1655   memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1656     outlen, (size_t) outlen);
1657
1658   LZX(window_posn) = window_posn;
1659   LZX(R0) = R0;
1660   LZX(R1) = R1;
1661   LZX(R2) = R2;
1662
1663   /* intel E8 decoding */
1664   if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1665     if (outlen <= 6 || !LZX(intel_started)) {
1666       LZX(intel_curpos) += outlen;
1667     }
1668     else {
1669       cab_UBYTE *data    = CAB(outbuf);
1670       cab_UBYTE *dataend = data + outlen - 10;
1671       cab_LONG curpos    = LZX(intel_curpos);
1672       cab_LONG filesize  = LZX(intel_filesize);
1673       cab_LONG abs_off, rel_off;
1674
1675       LZX(intel_curpos) = curpos + outlen;
1676
1677       while (data < dataend) {
1678         if (*data++ != 0xE8) { curpos++; continue; }
1679         abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1680         if ((abs_off >= -curpos) && (abs_off < filesize)) {
1681           rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1682           data[0] = (cab_UBYTE) rel_off;
1683           data[1] = (cab_UBYTE) (rel_off >> 8);
1684           data[2] = (cab_UBYTE) (rel_off >> 16);
1685           data[3] = (cab_UBYTE) (rel_off >> 24);
1686         }
1687         data += 4;
1688         curpos += 5;
1689       }
1690     }
1691   }
1692   return DECR_OK;
1693 }
1694
1695 /**********************************************************
1696  * fdi_decomp (internal)
1697  *
1698  * Decompress the "appropriate" number of bytes.  If savemode is zero,
1699  * do not save the output anywhere, just plow through blocks until we
1700  * reach the starting point for fi, and remember the position of the
1701  * cabfile pointer after we are done; otherwise, save it out, decompressing
1702  * the number of bytes in the file specified by fi.  This is also where we
1703  * jumping to additional cabinets in the case of split cab's, and provide
1704  * (most of) the NEXT_CABINET notification semantics described in the SDK.
1705  */
1706 int fdi_decomp(struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
1707   char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
1708 {
1709   cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
1710   cab_UBYTE buf[cfdata_SIZEOF], *data;
1711   cab_UWORD inlen, len, outlen, cando;
1712   cab_ULONG cksum;
1713   cab_LONG err;
1714   fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
1715
1716   TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
1717
1718   while (bytes > 0) {
1719     /* cando = the max number of bytes we can do */
1720     cando = CAB(outlen);
1721     if (cando > bytes) cando = bytes;
1722
1723     /* if cando != 0 */
1724     if (cando && savemode)
1725       PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
1726
1727     CAB(outpos) += cando;
1728     CAB(outlen) -= cando;
1729     bytes -= cando; if (!bytes) break;
1730
1731     /* we only get here if we emptied the output buffer */
1732
1733     /* read data header + data */
1734     inlen = outlen = 0;
1735     while (outlen == 0) {
1736       /* read the block header, skip the reserved part */
1737       if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
1738         return DECR_INPUT;
1739
1740       if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
1741         return DECR_INPUT;
1742
1743       /* we shouldn't get blocks over CAB_INPUTMAX in size */
1744       data = CAB(inbuf) + inlen;
1745       len = EndGetI16(buf+cfdata_CompressedSize);
1746       inlen += len;
1747       if (inlen > CAB_INPUTMAX) return DECR_INPUT;
1748       if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
1749         return DECR_INPUT;
1750
1751       /* clear two bytes after read-in data */
1752       data[len+1] = data[len+2] = 0;
1753
1754       /* perform checksum test on the block (if one is stored) */
1755       cksum = EndGetI32(buf+cfdata_CheckSum);
1756       if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
1757         return DECR_CHECKSUM; /* checksum is wrong */
1758
1759       outlen = EndGetI16(buf+cfdata_UncompressedSize);
1760
1761       /* outlen=0 means this block was the last contiguous part
1762          of a split block, continued in the next cabinet */
1763       if (outlen == 0) {
1764         int pathlen, filenamelen, idx, i, cabhf;
1765         char fullpath[MAX_PATH], userpath[256];
1766         FDINOTIFICATION fdin;
1767         FDICABINETINFO fdici;
1768         char emptystring = '\0';
1769         cab_UBYTE buf2[64];
1770         int success = FALSE;
1771         struct fdi_folder *fol = NULL, *linkfol = NULL; 
1772         struct fdi_file   *file = NULL, *linkfile = NULL;
1773
1774         tryanothercab:
1775
1776         /* set up the next decomp_state... */
1777         if (!(cab->next)) {
1778           if (!cab->mii.hasnext) return DECR_INPUT;
1779
1780           if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
1781             return DECR_NOMEMORY;
1782         
1783           ZeroMemory(cab->next, sizeof(fdi_decomp_state));
1784
1785           /* copy pszCabPath to userpath */
1786           ZeroMemory(userpath, 256);
1787           pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
1788           if (pathlen) {
1789             if (pathlen < 256) {
1790               for (i = 0; i <= pathlen; i++)
1791                 userpath[i] = pszCabPath[i];
1792             } /* else we are in a wierd place... let's leave it blank and see if the user fixes it */
1793           } 
1794
1795           /* initial fdintNEXT_CABINET notification */
1796           ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1797           fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
1798           fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
1799           fdin.psz3 = &userpath[0];
1800           fdin.fdie = FDIERROR_NONE;
1801           fdin.pv = pvUser;
1802
1803           if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1804
1805           do {
1806
1807             pathlen = (userpath) ? strlen(userpath) : 0;
1808             filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
1809
1810             /* slight overestimation here to save CPU cycles in the developer's brain */
1811             if ((pathlen + filenamelen + 3) > MAX_PATH) {
1812               ERR("MAX_PATH exceeded.\n");
1813               return DECR_ILLEGALDATA;
1814             }
1815
1816             /* paste the path and filename together */
1817             idx = 0;
1818             if (pathlen) {
1819               for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
1820               if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
1821             }
1822             if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
1823             fullpath[idx] = '\0';
1824         
1825             TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
1826         
1827             /* try to get a handle to the cabfile */
1828             cabhf = PFDI_OPEN(CAB(hfdi), fullpath, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
1829             if (cabhf == -1) {
1830               /* no file.  allow the user to try again */
1831               fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
1832               if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1833               continue;
1834             }
1835         
1836             /* check if it's really a cabfile. Note that this doesn't implement the bug */
1837             if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
1838               WARN("FDIIsCabinet failed.\n");
1839               PFDI_CLOSE(CAB(hfdi), cabhf);
1840               fdin.fdie = FDIERROR_NOT_A_CABINET;
1841               if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1842               continue;
1843             }
1844
1845             if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
1846               WARN("Wrong Cabinet.\n");
1847               PFDI_CLOSE(CAB(hfdi), cabhf);
1848               fdin.fdie = FDIERROR_WRONG_CABINET;
1849               if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
1850               continue;
1851             }
1852            
1853             break;
1854
1855           } while (1);
1856           
1857           /* cabinet notification */
1858           ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
1859           fdin.setID = fdici.setID;
1860           fdin.iCabinet = fdici.iCabinet;
1861           fdin.pv = pvUser;
1862           fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
1863           fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
1864           fdin.psz3 = pszCabPath;
1865         
1866           if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
1867           
1868           cab->next->setID = fdici.setID;
1869           cab->next->iCabinet = fdici.iCabinet;
1870           cab->next->hfdi = CAB(hfdi);
1871           cab->next->filehf = CAB(filehf);
1872           cab->next->cabhf = cabhf;
1873           cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
1874
1875           cab = cab->next; /* advance to the next cabinet */
1876
1877           /* read folders */
1878           for (i = 0; i < fdici.cFolders; i++) {
1879             if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF) 
1880               return DECR_INPUT;
1881
1882             if (cab->mii.folder_resv > 0)
1883               PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
1884         
1885             fol = (struct fdi_folder *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
1886             if (!fol) {
1887               ERR("out of memory!\n");
1888               return DECR_NOMEMORY;
1889             }
1890             ZeroMemory(fol, sizeof(struct fdi_folder));
1891             if (!(cab->firstfol)) cab->firstfol = fol;
1892         
1893             fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
1894             fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
1895             fol->comp_type  = EndGetI16(buf2+cffold_CompType);
1896         
1897             if (linkfol)
1898               linkfol->next = fol; 
1899             linkfol = fol;
1900           }
1901         
1902           /* read files */
1903           for (i = 0; i < fdici.cFiles; i++) {
1904             if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
1905               return DECR_INPUT;
1906               
1907             file = (struct fdi_file *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
1908             if (!file) {
1909               ERR("out of memory!\n"); 
1910               return DECR_NOMEMORY;
1911             }
1912             ZeroMemory(file, sizeof(struct fdi_file));
1913             if (!(cab->firstfile)) cab->firstfile = file;
1914               
1915             file->length   = EndGetI32(buf2+cffile_UncompressedSize);
1916             file->offset   = EndGetI32(buf2+cffile_FolderOffset);
1917             file->index    = EndGetI16(buf2+cffile_FolderIndex);
1918             file->time     = EndGetI16(buf2+cffile_Time);
1919             file->date     = EndGetI16(buf2+cffile_Date);
1920             file->attribs  = EndGetI16(buf2+cffile_Attribs);
1921             file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
1922         
1923             if (!file->filename) return DECR_INPUT;
1924         
1925             if (linkfile)
1926               linkfile->next = file;
1927             linkfile = file;
1928           }
1929         
1930         } else 
1931             cab = cab->next; /* advance to the next cabinet */
1932
1933         /* iterate files -- if we encounter the continued file, process it --
1934            otherwise, jump to the label above and keep looking */
1935
1936         for (file = cab->firstfile; (file); file = file->next) {
1937           if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
1938             /* check to ensure a real match */
1939             if (strcasecmp(fi->filename, file->filename) == 0) {
1940               success = TRUE;
1941               if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
1942                 return DECR_INPUT;
1943               break;
1944             }
1945           }
1946         }
1947         if (!success) goto tryanothercab; /* this should never happen */
1948       }
1949     }
1950
1951     /* decompress block */
1952     if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
1953       return err;
1954     CAB(outlen) = outlen;
1955     CAB(outpos) = CAB(outbuf);
1956   }
1957   
1958   CAB(decomp_cab) = cab;
1959   return DECR_OK;
1960 }
1961
1962 /***********************************************************************
1963  *              FDICopy (CABINET.22)
1964  */
1965 BOOL __cdecl FDICopy(
1966         HFDI           hfdi,
1967         char          *pszCabinet,
1968         char          *pszCabPath,
1969         int            flags,
1970         PFNFDINOTIFY   pfnfdin,
1971         PFNFDIDECRYPT  pfnfdid,
1972         void          *pvUser)
1973
1974   FDICABINETINFO    fdici;
1975   FDINOTIFICATION   fdin;
1976   int               cabhf, filehf;
1977   int               i, idx;
1978   char              fullpath[MAX_PATH];
1979   size_t            pathlen, filenamelen;
1980   char              emptystring = '\0';
1981   cab_UBYTE         buf[64];
1982   struct fdi_folder *fol = NULL, *linkfol = NULL; 
1983   struct fdi_file   *file = NULL, *linkfile = NULL;
1984   fdi_decomp_state _decomp_state;
1985   fdi_decomp_state *decomp_state = &_decomp_state;
1986
1987   TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, \
1988         pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
1989         hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
1990
1991   if (!REALLY_IS_FDI(hfdi)) {
1992     SetLastError(ERROR_INVALID_HANDLE);
1993     return FALSE;
1994   }
1995
1996   ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
1997
1998   pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
1999   filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2000
2001   /* slight overestimation here to save CPU cycles in the developer's brain */
2002   if ((pathlen + filenamelen + 3) > MAX_PATH) {
2003     ERR("MAX_PATH exceeded.\n");
2004     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2005     PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2006     PFDI_INT(hfdi)->perf->fError = TRUE;
2007     SetLastError(ERROR_FILE_NOT_FOUND);
2008     return FALSE;
2009   }
2010
2011   /* paste the path and filename together */
2012   idx = 0;
2013   if (pathlen) {
2014     for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2015     if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2016   }
2017   if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2018   fullpath[idx] = '\0';
2019
2020   TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2021
2022   /* get a handle to the cabfile */
2023   cabhf = PFDI_OPEN(hfdi, fullpath, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL, 0);
2024   if (cabhf == -1) {
2025     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2026     PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2027     PFDI_INT(hfdi)->perf->fError = TRUE;
2028     SetLastError(ERROR_FILE_NOT_FOUND);
2029     return FALSE;
2030   }
2031
2032   /* check if it's really a cabfile. Note that this doesn't implement the bug */
2033   if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2034     ERR("FDIIsCabinet failed.\n");
2035     PFDI_CLOSE(hfdi, cabhf);
2036     return FALSE;
2037   }
2038    
2039   /* cabinet notification */
2040   ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2041   fdin.setID = fdici.setID;
2042   fdin.iCabinet = fdici.iCabinet;
2043   fdin.pv = pvUser;
2044   fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2045   fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2046   fdin.psz3 = pszCabPath;
2047
2048   if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2049     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2050     PFDI_INT(hfdi)->perf->erfType = 0;
2051     PFDI_INT(hfdi)->perf->fError = TRUE;
2052     goto bail_and_fail;
2053   }
2054
2055   CAB(setID) = fdici.setID;
2056   CAB(iCabinet) = fdici.iCabinet;
2057
2058   /* read folders */
2059   for (i = 0; i < fdici.cFolders; i++) {
2060     if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2061       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2062       PFDI_INT(hfdi)->perf->erfType = 0;
2063       PFDI_INT(hfdi)->perf->fError = TRUE;
2064       goto bail_and_fail;
2065     }
2066
2067     if (CAB(mii).folder_resv > 0)
2068       PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2069
2070     fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2071     if (!fol) {
2072       ERR("out of memory!\n");
2073       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2074       PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2075       PFDI_INT(hfdi)->perf->fError = TRUE;
2076       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2077       goto bail_and_fail;
2078     }
2079     ZeroMemory(fol, sizeof(struct fdi_folder));
2080     if (!CAB(firstfol)) CAB(firstfol) = fol;
2081
2082     fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2083     fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2084     fol->comp_type  = EndGetI16(buf+cffold_CompType);
2085
2086     if (linkfol)
2087       linkfol->next = fol; 
2088     linkfol = fol;
2089   }
2090
2091   /* read files */
2092   for (i = 0; i < fdici.cFiles; i++) {
2093     if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2094       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2095       PFDI_INT(hfdi)->perf->erfType = 0;
2096       PFDI_INT(hfdi)->perf->fError = TRUE;
2097       goto bail_and_fail;
2098     }
2099
2100     file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2101     if (!file) { 
2102       ERR("out of memory!\n"); 
2103       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2104       PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2105       PFDI_INT(hfdi)->perf->fError = TRUE;
2106       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2107       goto bail_and_fail;
2108     }
2109     ZeroMemory(file, sizeof(struct fdi_file));
2110     if (!CAB(firstfile)) CAB(firstfile) = file;
2111       
2112     file->length   = EndGetI32(buf+cffile_UncompressedSize);
2113     file->offset   = EndGetI32(buf+cffile_FolderOffset);
2114     file->index    = EndGetI16(buf+cffile_FolderIndex);
2115     file->time     = EndGetI16(buf+cffile_Time);
2116     file->date     = EndGetI16(buf+cffile_Date);
2117     file->attribs  = EndGetI16(buf+cffile_Attribs);
2118     file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2119
2120     if (!file->filename) {
2121       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2122       PFDI_INT(hfdi)->perf->erfType = 0;
2123       PFDI_INT(hfdi)->perf->fError = TRUE;
2124       goto bail_and_fail;
2125     }
2126
2127     if (linkfile)
2128       linkfile->next = file;
2129     linkfile = file;
2130   }
2131
2132   for (file = CAB(firstfile); (file); file = file->next) {
2133     /* partial-file notification (do it just once for the first cabinet) */
2134     if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2135       /* OK, more MS bugs to simulate here, I think.  I don't have a huge spanning
2136        * cabinet to test this theory on ATM, but here's the deal.  The SDK says that we
2137        * are supposed to notify the user of the filename and "disk name" (info) of
2138        * the cabinet where the spanning file /started/.  That would certainly be convenient
2139        * for the consumer, who could decide to abort everything and try to start over with
2140        * that cabinet so as to avoid partial file notification and successfully unpack.  This
2141        * task would be a horrible bitch from the implementor's (wine's) perspective: the
2142        * information is associated nowhere with the file header and is not to be found in
2143        * the cabinet header.  So we would have to open the previous cabinet, and check
2144        * if it contains a single spanning file that's continued from yet another prior cabinet,
2145        * and so-on, until we find the beginning.  Note that cabextract.c has code to do exactly
2146        * this.  Luckily, MS clearly didn't implement this logic, so we don't have to either.
2147        * Watching the callbacks (and debugmsg +file) clearly shows that they don't open
2148        * the preceeding cabinet -- and therefore, I deduce, there is NO WAY they could
2149        * have implemented what's in the spec.  Instead, they are obviously just returning
2150        * the previous cabinet and it's info from the header of this cabinet.  So we shall
2151        * do the same.  Of course, I could be missing something...
2152        */
2153       ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2154       fdin.pv = pvUser;
2155       fdin.psz1 = (char *)file->filename;
2156       fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2157       fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2158
2159       if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2160         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2161         PFDI_INT(hfdi)->perf->erfType = 0;
2162         PFDI_INT(hfdi)->perf->fError = TRUE;
2163         goto bail_and_fail;
2164       }
2165       /* I don't think we are supposed to decompress partial files.  This prevents it. */
2166       file->oppressed = TRUE;
2167     }
2168     if (file->oppressed) {
2169       filehf = 0;
2170     } else {
2171       ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2172       fdin.pv = pvUser;
2173       fdin.psz1 = (char *)file->filename;
2174       fdin.cb = file->length;
2175       fdin.date = file->date;
2176       fdin.time = file->time;
2177       fdin.attribs = file->attribs;
2178       if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2179         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2180         PFDI_INT(hfdi)->perf->erfType = 0;
2181         PFDI_INT(hfdi)->perf->fError = TRUE;
2182         goto bail_and_fail;
2183       }
2184     }
2185
2186     /* find the folder for this file if necc. */
2187     if (filehf) {
2188       int i2;
2189
2190       fol = CAB(firstfol);
2191       if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2192         /* pick the last folder */
2193         while (fol->next) fol = fol->next;
2194       } else {
2195         for (i2 = 0; (i2 < file->index); i2++)
2196           if (fol->next) /* bug resistance, should always be true */
2197             fol = fol->next;
2198       }
2199     }
2200
2201     if (filehf) {
2202       cab_UWORD comptype = fol->comp_type;
2203       int ct1 = comptype & cffoldCOMPTYPE_MASK;
2204       int err = 0;
2205
2206       TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2207
2208       /* set up decomp_state */
2209       CAB(hfdi) = hfdi;
2210       CAB(filehf) = filehf;
2211       CAB(cabhf) = cabhf;
2212       CAB(current) = fol;
2213       CAB(decomp_cab) = NULL;
2214
2215       /* set up the appropriate decompressor */
2216       switch (ct1) {
2217         case cffoldCOMPTYPE_NONE:
2218           CAB(decompress) = NONEfdi_decomp;
2219           break;
2220         case cffoldCOMPTYPE_MSZIP:
2221           CAB(decompress) = ZIPfdi_decomp;
2222           break;
2223         case cffoldCOMPTYPE_QUANTUM:
2224           CAB(decompress) = QTMfdi_decomp;
2225           err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2226           break;
2227         case cffoldCOMPTYPE_LZX:
2228           CAB(decompress) = LZXfdi_decomp;
2229           err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2230           break;
2231         default:
2232           err = DECR_DATAFORMAT;
2233       }
2234
2235       switch (err) {
2236         case DECR_OK:
2237           break;
2238         case DECR_NOMEMORY:
2239           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2240           PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2241           PFDI_INT(hfdi)->perf->fError = TRUE;
2242           SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2243           goto bail_and_fail;
2244         default:
2245           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2246           PFDI_INT(hfdi)->perf->erfOper = 0;
2247           PFDI_INT(hfdi)->perf->fError = TRUE;
2248           goto bail_and_fail;
2249       }
2250
2251       PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2252       CAB(offset) = 0;
2253       CAB(outlen) = 0;
2254
2255       if (file->offset > CAB(offset)) {
2256         /* decode bytes and send them to /dev/null */
2257         switch ((err = fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser))) {
2258           case DECR_OK:
2259             break;
2260           case DECR_USERABORT:
2261             PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2262             PFDI_INT(hfdi)->perf->erfType = 0;
2263             PFDI_INT(hfdi)->perf->fError = TRUE;
2264             goto bail_and_fail;
2265           case DECR_NOMEMORY:
2266             PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2267             PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2268             PFDI_INT(hfdi)->perf->fError = TRUE;
2269             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2270             goto bail_and_fail;
2271           default:
2272             PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2273             PFDI_INT(hfdi)->perf->erfOper = 0;
2274             PFDI_INT(hfdi)->perf->fError = TRUE;
2275             goto bail_and_fail;
2276         }
2277         CAB(offset) = file->offset;
2278       }
2279
2280       /* now do the actual decompression */
2281       err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2282       if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2283
2284       switch (err) {
2285         case DECR_OK:
2286           break;
2287         case DECR_USERABORT:
2288           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2289           PFDI_INT(hfdi)->perf->erfType = 0;
2290           PFDI_INT(hfdi)->perf->fError = TRUE;
2291           goto bail_and_fail;
2292         case DECR_NOMEMORY:
2293           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2294           PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2295           PFDI_INT(hfdi)->perf->fError = TRUE;
2296           SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2297           goto bail_and_fail;
2298         default:
2299           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2300           PFDI_INT(hfdi)->perf->erfOper = 0;
2301           PFDI_INT(hfdi)->perf->fError = TRUE;
2302           goto bail_and_fail;
2303       }
2304
2305       /* free decompression temps */
2306       switch (ct1) {
2307         case cffoldCOMPTYPE_LZX:
2308           if (LZX(window)) {
2309             PFDI_FREE(hfdi, LZX(window));
2310             LZX(window) = NULL;
2311           }
2312           break;
2313         case cffoldCOMPTYPE_QUANTUM:
2314           if (QTM(window)) {
2315             PFDI_FREE(hfdi, QTM(window));
2316             QTM(window) = NULL;
2317           }
2318           break;
2319         default:
2320           break;
2321       }
2322
2323       /* fdintCLOSE_FILE_INFO notification */
2324       ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2325       fdin.pv = pvUser;
2326       fdin.psz1 = (char *)file->filename;
2327       fdin.hf = filehf;
2328       fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE;
2329       fdin.date = file->date;
2330       fdin.time = file->time;
2331       fdin.attribs = file->attribs;
2332       err = ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2333       if (err == FALSE || err == -1) {
2334         /*
2335          * SDK states that even though they indicated failure,
2336          * we are not supposed to try and close the file, so we
2337          * just treat this like all the others
2338          */
2339         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2340         PFDI_INT(hfdi)->perf->erfType = 0;
2341         PFDI_INT(hfdi)->perf->fError = TRUE;
2342         goto bail_and_fail;
2343       }
2344     }
2345   }
2346
2347   while (decomp_state) {
2348     fdi_decomp_state *prev_fds;
2349
2350     PFDI_CLOSE(hfdi, CAB(cabhf));
2351
2352     /* free the storage remembered by mii */
2353     if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2354     if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2355     if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2356     if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2357
2358     while (CAB(firstfol)) {
2359       fol = CAB(firstfol);
2360       CAB(firstfol) = CAB(firstfol)->next;
2361       PFDI_FREE(hfdi, fol);
2362     }
2363     while (CAB(firstfile)) {
2364       file = CAB(firstfile);
2365       if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2366       CAB(firstfile) = CAB(firstfile)->next;
2367       PFDI_FREE(hfdi, file);
2368     }
2369     prev_fds = decomp_state;
2370     decomp_state = CAB(next);
2371     if (prev_fds != &_decomp_state)
2372       PFDI_FREE(hfdi, prev_fds);
2373   }
2374  
2375   return TRUE;
2376
2377   bail_and_fail: /* here we free ram before error returns */
2378
2379   while (decomp_state) {
2380     fdi_decomp_state *prev_fds;
2381
2382     PFDI_CLOSE(hfdi, CAB(cabhf));
2383
2384     /* free the storage remembered by mii */
2385     if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2386     if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2387     if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2388     if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2389
2390     while (CAB(firstfol)) {
2391       fol = CAB(firstfol);
2392       CAB(firstfol) = CAB(firstfol)->next;
2393       PFDI_FREE(hfdi, fol);
2394     }
2395     while (CAB(firstfile)) {
2396       file = CAB(firstfile);
2397       if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2398       CAB(firstfile) = CAB(firstfile)->next;
2399       PFDI_FREE(hfdi, file);
2400     }
2401     prev_fds = decomp_state;
2402     decomp_state = CAB(next);
2403     if (prev_fds != &_decomp_state)
2404       PFDI_FREE(hfdi, prev_fds);
2405   }
2406
2407   return FALSE;
2408 }
2409
2410 /***********************************************************************
2411  *              FDIDestroy (CABINET.23)
2412  */
2413 BOOL __cdecl FDIDestroy(HFDI hfdi)
2414 {
2415   TRACE("(hfdi == ^%p)\n", hfdi);
2416   if (REALLY_IS_FDI(hfdi)) {
2417     PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2418     PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2419     return TRUE;
2420   } else {
2421     SetLastError(ERROR_INVALID_HANDLE);
2422     return FALSE;
2423   }
2424 }
2425
2426 /***********************************************************************
2427  *              FDITruncateCabinet (CABINET.24)
2428  */
2429 BOOL __cdecl FDITruncateCabinet(
2430         HFDI    hfdi,
2431         char   *pszCabinetName,
2432         USHORT  iFolderToDelete)
2433 {
2434   FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2435     hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2436
2437   if (!REALLY_IS_FDI(hfdi)) {
2438     SetLastError(ERROR_INVALID_HANDLE);
2439     return FALSE;
2440   }
2441
2442   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2443   return FALSE;
2444 }