crypt32: Initialize mask when allocating it.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  *
22  *
23  * This is a largely redundant reimplementation of the stuff in cabextract.c.  It
24  * would be theoretically preferable to have only one, shared implementation, however
25  * there are semantic differences which may discourage efforts to unify the two.  It
26  * should be possible, if awkward, to go back and reimplement cabextract.c using FDI.
27  * But this approach would be quite a bit less performant.  Probably a better way
28  * would be to create a "library" of routines in cabextract.c which do the actual
29  * decompression, and have both fdi.c and cabextract share those routines.  The rest
30  * of the code is not sufficiently similar to merit a shared implementation.
31  *
32  * The worst thing about this API is the bug.  "The bug" is this: when you extract a
33  * cabinet, it /always/ informs you (via the hasnext field of PFDICABINETINFO), that
34  * there is no subsequent cabinet, even if there is one.  wine faithfully reproduces
35  * this behavior.
36  *
37  * TODO:
38  *
39  * Wine does not implement the AFAIK undocumented "enumerate" callback during
40  * FDICopy.  It is implemented in Windows and therefore worth investigating...
41  *
42  * Lots of pointers flying around here... am I leaking RAM?
43  *
44  * WTF is FDITruncate?
45  *
46  * Probably, I need to weed out some dead code-paths.
47  *
48  * Test unit(s).
49  *
50  * The fdintNEXT_CABINET callbacks are probably not working quite as they should.
51  * There are several FIXME's in the source describing some of the deficiencies in
52  * some detail.  Additionally, we do not do a very good job of returning the right
53  * error codes to this callback.
54  *
55  * FDICopy and fdi_decomp are incomprehensibly large; separating these into smaller
56  * functions would be nice.
57  *
58  *   -gmt
59  */
60
61 #include "config.h"
62
63 #include <stdarg.h>
64 #include <stdio.h>
65
66 #include "windef.h"
67 #include "winbase.h"
68 #include "winerror.h"
69 #include "fdi.h"
70 #include "cabinet.h"
71
72 #include "wine/debug.h"
73
74 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
75
76 THOSE_ZIP_CONSTS;
77
78 struct fdi_file {
79   struct fdi_file *next;               /* next file in sequence          */
80   LPCSTR filename;                     /* output name of file            */
81   int    fh;                           /* open file handle or NULL       */
82   cab_ULONG length;                    /* uncompressed length of file    */
83   cab_ULONG offset;                    /* uncompressed offset in folder  */
84   cab_UWORD index;                     /* magic index number of folder   */
85   cab_UWORD time, date, attribs;       /* MS-DOS time/date/attributes    */
86   BOOL oppressed;                      /* never to be processed          */
87 };
88
89 struct fdi_folder {
90   struct fdi_folder *next;
91   cab_off_t offset;                    /* offset to data blocks (32 bit) */
92   cab_UWORD comp_type;                 /* compression format/window size */
93   cab_ULONG comp_size;                 /* compressed size of folder      */
94   cab_UBYTE num_splits;                /* number of split blocks + 1     */
95   cab_UWORD num_blocks;                /* total number of blocks         */
96 };
97
98 /*
99  * this structure fills the gaps between what is available in a PFDICABINETINFO
100  * vs what is needed by FDICopy.  Memory allocated for these becomes the responsibility
101  * of the caller to free.  Yes, I am aware that this is totally, utterly inelegant.
102  * To make things even more unnecessarily confusing, we now attach these to the
103  * fdi_decomp_state.
104  */
105 typedef struct {
106    char *prevname, *previnfo;
107    char *nextname, *nextinfo;
108    BOOL hasnext;  /* bug free indicator */
109    int folder_resv, header_resv;
110    cab_UBYTE block_resv;
111 } MORE_ISCAB_INFO, *PMORE_ISCAB_INFO;
112
113 /*
114  * ugh, well, this ended up being pretty damn silly...
115  * now that I've conceded to build equivalent structures to struct cab.*,
116  * I should have just used those, or, better yet, unified the two... sue me.
117  * (Note to Microsoft: That's a joke.  Please /don't/ actually sue me! -gmt).
118  * Nevertheless, I've come this far, it works, so I'm not gonna change it
119  * for now.  This implementation has significant semantic differences anyhow.
120  */
121
122 typedef struct fdi_cds_fwd {
123   void *hfdi;                      /* the hfdi we are using                 */
124   int filehf, cabhf;               /* file handle we are using              */
125   struct fdi_folder *current;      /* current folder we're extracting from  */
126   cab_ULONG offset;                /* uncompressed offset within folder     */
127   cab_UBYTE *outpos;               /* (high level) start of data to use up  */
128   cab_UWORD outlen;                /* (high level) amount of data to use up */
129   int (*decompress)(int, int, struct fdi_cds_fwd *); /* chosen compress fn  */
130   cab_UBYTE inbuf[CAB_INPUTMAX+2]; /* +2 for lzx bitbuffer overflows!       */
131   cab_UBYTE outbuf[CAB_BLOCKMAX];
132   union {
133     struct ZIPstate zip;
134     struct QTMstate qtm;
135     struct LZXstate lzx;
136   } methods;
137   /* some temp variables for use during decompression */
138   cab_UBYTE q_length_base[27], q_length_extra[27], q_extra_bits[42];
139   cab_ULONG q_position_base[42];
140   cab_ULONG lzx_position_base[51];
141   cab_UBYTE extra_bits[51];
142   USHORT  setID;                   /* Cabinet set ID */
143   USHORT  iCabinet;                /* Cabinet number in set (0 based) */
144   struct fdi_cds_fwd *decomp_cab;
145   MORE_ISCAB_INFO mii;
146   struct fdi_folder *firstfol; 
147   struct fdi_file   *firstfile;
148   struct fdi_cds_fwd *next;
149 } fdi_decomp_state;
150
151 /****************************************************************
152  * QTMupdatemodel (internal)
153  */
154 void QTMupdatemodel(struct QTMmodel *model, int sym) {
155   struct QTMmodelsym temp;
156   int i, j;
157
158   for (i = 0; i < sym; i++) model->syms[i].cumfreq += 8;
159
160   if (model->syms[0].cumfreq > 3800) {
161     if (--model->shiftsleft) {
162       for (i = model->entries - 1; i >= 0; i--) {
163     /* -1, not -2; the 0 entry saves this */
164     model->syms[i].cumfreq >>= 1;
165     if (model->syms[i].cumfreq <= model->syms[i+1].cumfreq) {
166       model->syms[i].cumfreq = model->syms[i+1].cumfreq + 1;
167     }
168       }
169     }
170     else {
171       model->shiftsleft = 50;
172       for (i = 0; i < model->entries ; i++) {
173     /* no -1, want to include the 0 entry */
174     /* this converts cumfreqs into frequencies, then shifts right */
175     model->syms[i].cumfreq -= model->syms[i+1].cumfreq;
176     model->syms[i].cumfreq++; /* avoid losing things entirely */
177     model->syms[i].cumfreq >>= 1;
178       }
179
180       /* now sort by frequencies, decreasing order -- this must be an
181        * inplace selection sort, or a sort with the same (in)stability
182        * characteristics
183        */
184       for (i = 0; i < model->entries - 1; i++) {
185     for (j = i + 1; j < model->entries; j++) {
186       if (model->syms[i].cumfreq < model->syms[j].cumfreq) {
187         temp = model->syms[i];
188         model->syms[i] = model->syms[j];
189         model->syms[j] = temp;
190       }
191     }
192       }
193     
194       /* then convert frequencies back to cumfreq */
195       for (i = model->entries - 1; i >= 0; i--) {
196     model->syms[i].cumfreq += model->syms[i+1].cumfreq;
197       }
198       /* then update the other part of the table */
199       for (i = 0; i < model->entries; i++) {
200     model->tabloc[model->syms[i].sym] = i;
201       }
202     }
203   }
204 }
205
206 /*************************************************************************
207  * make_decode_table (internal)
208  *
209  * This function was coded by David Tritscher. It builds a fast huffman
210  * decoding table out of just a canonical huffman code lengths table.
211  *
212  * PARAMS
213  *   nsyms:  total number of symbols in this huffman tree.
214  *   nbits:  any symbols with a code length of nbits or less can be decoded
215  *           in one lookup of the table.
216  *   length: A table to get code lengths from [0 to syms-1]
217  *   table:  The table to fill up with decoded symbols and pointers.
218  *
219  * RETURNS
220  *   OK:    0
221  *   error: 1
222  */
223 int make_decode_table(cab_ULONG nsyms, cab_ULONG nbits, const cab_UBYTE *length, cab_UWORD *table) {
224   register cab_UWORD sym;
225   register cab_ULONG leaf;
226   register cab_UBYTE bit_num = 1;
227   cab_ULONG fill;
228   cab_ULONG pos         = 0; /* the current position in the decode table */
229   cab_ULONG table_mask  = 1 << nbits;
230   cab_ULONG bit_mask    = table_mask >> 1; /* don't do 0 length codes */
231   cab_ULONG next_symbol = bit_mask; /* base of allocation for long codes */
232
233   /* fill entries for codes short enough for a direct mapping */
234   while (bit_num <= nbits) {
235     for (sym = 0; sym < nsyms; sym++) {
236       if (length[sym] == bit_num) {
237         leaf = pos;
238
239         if((pos += bit_mask) > table_mask) return 1; /* table overrun */
240
241         /* fill all possible lookups of this symbol with the symbol itself */
242         fill = bit_mask;
243         while (fill-- > 0) table[leaf++] = sym;
244       }
245     }
246     bit_mask >>= 1;
247     bit_num++;
248   }
249
250   /* if there are any codes longer than nbits */
251   if (pos != table_mask) {
252     /* clear the remainder of the table */
253     for (sym = pos; sym < table_mask; sym++) table[sym] = 0;
254
255     /* give ourselves room for codes to grow by up to 16 more bits */
256     pos <<= 16;
257     table_mask <<= 16;
258     bit_mask = 1 << 15;
259
260     while (bit_num <= 16) {
261       for (sym = 0; sym < nsyms; sym++) {
262         if (length[sym] == bit_num) {
263           leaf = pos >> 16;
264           for (fill = 0; fill < bit_num - nbits; fill++) {
265             /* if this path hasn't been taken yet, 'allocate' two entries */
266             if (table[leaf] == 0) {
267               table[(next_symbol << 1)] = 0;
268               table[(next_symbol << 1) + 1] = 0;
269               table[leaf] = next_symbol++;
270             }
271             /* follow the path and select either left or right for next bit */
272             leaf = table[leaf] << 1;
273             if ((pos >> (15-fill)) & 1) leaf++;
274           }
275           table[leaf] = sym;
276
277           if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
278         }
279       }
280       bit_mask >>= 1;
281       bit_num++;
282     }
283   }
284
285   /* full table? */
286   if (pos == table_mask) return 0;
287
288   /* either erroneous table, or all elements are 0 - let's find out. */
289   for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1;
290   return 0;
291 }
292
293 /*************************************************************************
294  * checksum (internal)
295  */
296 cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum) {
297   int len;
298   cab_ULONG ul = 0;
299
300   for (len = bytes >> 2; len--; data += 4) {
301     csum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
302   }
303
304   switch (bytes & 3) {
305   case 3: ul |= *data++ << 16;
306   case 2: ul |= *data++ <<  8;
307   case 1: ul |= *data;
308   }
309   csum ^= ul;
310
311   return csum;
312 }
313
314 /***********************************************************************
315  *              FDICreate (CABINET.20)
316  *
317  * Provided with several callbacks (all of them are mandatory),
318  * returns a handle which can be used to perform operations
319  * on cabinet files.
320  *
321  * PARAMS
322  *   pfnalloc [I]  A pointer to a function which allocates ram.  Uses
323  *                 the same interface as malloc.
324  *   pfnfree  [I]  A pointer to a function which frees ram.  Uses the
325  *                 same interface as free.
326  *   pfnopen  [I]  A pointer to a function which opens a file.  Uses
327  *                 the same interface as _open.
328  *   pfnread  [I]  A pointer to a function which reads from a file into
329  *                 a caller-provided buffer.  Uses the same interface
330  *                 as _read
331  *   pfnwrite [I]  A pointer to a function which writes to a file from
332  *                 a caller-provided buffer.  Uses the same interface
333  *                 as _write.
334  *   pfnclose [I]  A pointer to a function which closes a file handle.
335  *                 Uses the same interface as _close.
336  *   pfnseek  [I]  A pointer to a function which seeks in a file.
337  *                 Uses the same interface as _lseek.
338  *   cpuType  [I]  The type of CPU; ignored in wine (recommended value:
339  *                 cpuUNKNOWN, aka -1).
340  *   perf     [IO] A pointer to an ERF structure.  When FDICreate
341  *                 returns an error condition, error information may
342  *                 be found here as well as from GetLastError.
343  *
344  * RETURNS
345  *   On success, returns an FDI handle of type HFDI.
346  *   On failure, the NULL file handle is returned. Error
347  *   info can be retrieved from perf.
348  *
349  * INCLUDES
350  *   fdi.h
351  * 
352  */
353 HFDI __cdecl FDICreate(
354         PFNALLOC pfnalloc,
355         PFNFREE  pfnfree,
356         PFNOPEN  pfnopen,
357         PFNREAD  pfnread,
358         PFNWRITE pfnwrite,
359         PFNCLOSE pfnclose,
360         PFNSEEK  pfnseek,
361         int      cpuType,
362         PERF     perf)
363 {
364   HFDI rv;
365
366   TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, "
367         "pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
368         pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
369         cpuType, perf);
370
371   if ((!pfnalloc) || (!pfnfree)) {
372     perf->erfOper = FDIERROR_NONE;
373     perf->erfType = ERROR_BAD_ARGUMENTS;
374     perf->fError = TRUE;
375
376     SetLastError(ERROR_BAD_ARGUMENTS);
377     return NULL;
378   }
379
380   if (!((rv = ((HFDI) (*pfnalloc)(sizeof(FDI_Int)))))) {
381     perf->erfOper = FDIERROR_ALLOC_FAIL;
382     perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
383     perf->fError = TRUE;
384
385     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
386     return NULL;
387   }
388   
389   PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
390   PFDI_INT(rv)->pfnalloc = pfnalloc;
391   PFDI_INT(rv)->pfnfree = pfnfree;
392   PFDI_INT(rv)->pfnopen = pfnopen;
393   PFDI_INT(rv)->pfnread = pfnread;
394   PFDI_INT(rv)->pfnwrite = pfnwrite;
395   PFDI_INT(rv)->pfnclose = pfnclose;
396   PFDI_INT(rv)->pfnseek = pfnseek;
397   /* no-brainer: we ignore the cpu type; this is only used
398      for the 16-bit versions in Windows anyhow... */
399   PFDI_INT(rv)->perf = perf;
400
401   return rv;
402 }
403
404 /*******************************************************************
405  * FDI_getoffset (internal)
406  *
407  * returns the file pointer position of a file handle.
408  */
409 static long FDI_getoffset(HFDI hfdi, INT_PTR hf)
410 {
411   return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
412 }
413
414 /**********************************************************************
415  * FDI_read_string (internal)
416  *
417  * allocate and read an arbitrarily long string from the cabinet
418  */
419 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
420 {
421   size_t len=256,
422          base = FDI_getoffset(hfdi, hf),
423          maxlen = cabsize - base;
424   BOOL ok = FALSE;
425   unsigned int i;
426   cab_UBYTE *buf = NULL;
427
428   TRACE("(hfdi == ^%p, hf == %ld, cabsize == %ld)\n", hfdi, hf, cabsize);
429
430   do {
431     if (len > maxlen) len = maxlen;
432     if (!(buf = PFDI_ALLOC(hfdi, len))) break;
433     if (!PFDI_READ(hfdi, hf, buf, len)) break;
434
435     /* search for a null terminator in what we've just read */
436     for (i=0; i < len; i++) {
437       if (!buf[i]) {ok=TRUE; break;}
438     }
439
440     if (!ok) {
441       if (len == maxlen) {
442         ERR("cabinet is truncated\n");
443         break;
444       }
445       /* The buffer is too small for the string. Reset the file to the point
446        * were we started, free the buffer and increase the size for the next try
447        */
448       PFDI_SEEK(hfdi, hf, base, SEEK_SET);
449       PFDI_FREE(hfdi, buf);
450       buf = NULL;
451       len *= 2;
452     }
453   } while (!ok);
454
455   if (!ok) {
456     if (buf)
457       PFDI_FREE(hfdi, buf);
458     else
459       ERR("out of memory!\n");
460     return NULL;
461   }
462
463   /* otherwise, set the stream to just after the string and return */
464   PFDI_SEEK(hfdi, hf, base + ((cab_off_t) strlen((char *) buf)) + 1, SEEK_SET);
465
466   return (char *) buf;
467 }
468
469 /******************************************************************
470  * FDI_read_entries (internal)
471  *
472  * process the cabinet header in the style of FDIIsCabinet, but
473  * without the sanity checks (and bug)
474  */
475 static BOOL FDI_read_entries(
476         HFDI             hfdi,
477         INT_PTR          hf,
478         PFDICABINETINFO  pfdici,
479         PMORE_ISCAB_INFO pmii)
480 {
481   int num_folders, num_files, header_resv, folder_resv = 0;
482   LONG base_offset, cabsize;
483   USHORT setid, cabidx, flags;
484   cab_UBYTE buf[64], block_resv;
485   char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
486
487   TRACE("(hfdi == ^%p, hf == %ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
488
489   /* 
490    * FIXME: I just noticed that I am memorizing the initial file pointer
491    * offset and restoring it before reading in the rest of the header
492    * information in the cabinet.  Perhaps that's correct -- that is, perhaps
493    * this API is supposed to support "streaming" cabinets which are embedded
494    * in other files, or cabinets which begin at file offsets other than zero.
495    * Otherwise, I should instead go to the absolute beginning of the file.
496    * (Either way, the semantics of wine's FDICopy require me to leave the
497    * file pointer where it is afterwards -- If Windows does not do so, we
498    * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
499    * 
500    * So, the answer lies in Windows; will native cabinet.dll recognize a
501    * cabinet "file" embedded in another file?  Note that cabextract.c does
502    * support this, which implies that Microsoft's might.  I haven't tried it
503    * yet so I don't know.  ATM, most of wine's FDI cabinet routines (except
504    * this one) would not work in this way.  To fix it, we could just make the
505    * various references to absolute file positions in the code relative to an
506    * initial "beginning" offset.  Because the FDICopy API doesn't take a
507    * file-handle like this one, we would therein need to search through the
508    * file for the beginning of the cabinet (as we also do in cabextract.c).
509    * Note that this limits us to a maximum of one cabinet per. file: the first.
510    *
511    * So, in summary: either the code below is wrong, or the rest of fdi.c is
512    * wrong... I cannot imagine that both are correct ;)  One of these flaws
513    * should be fixed after determining the behavior on Windows.   We ought
514    * to check both FDIIsCabinet and FDICopy for the right behavior.
515    *
516    * -gmt
517    */
518
519   /* get basic offset & size info */
520   base_offset = FDI_getoffset(hfdi, hf);
521
522   if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
523     if (pmii) {
524       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
525       PFDI_INT(hfdi)->perf->erfType = 0;
526       PFDI_INT(hfdi)->perf->fError = TRUE;
527     }
528     return FALSE;
529   }
530
531   cabsize = FDI_getoffset(hfdi, hf);
532
533   if ((cabsize == -1) || (base_offset == -1) || 
534       ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
535     if (pmii) {
536       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
537       PFDI_INT(hfdi)->perf->erfType = 0;
538       PFDI_INT(hfdi)->perf->fError = TRUE;
539     }
540     return FALSE;
541   }
542
543   /* read in the CFHEADER */
544   if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
545     if (pmii) {
546       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
547       PFDI_INT(hfdi)->perf->erfType = 0;
548       PFDI_INT(hfdi)->perf->fError = TRUE;
549     }
550     return FALSE;
551   }
552   
553   /* check basic MSCF signature */
554   if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
555     if (pmii) {
556       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
557       PFDI_INT(hfdi)->perf->erfType = 0;
558       PFDI_INT(hfdi)->perf->fError = TRUE;
559     }
560     return FALSE;
561   }
562
563   /* get the number of folders */
564   num_folders = EndGetI16(buf+cfhead_NumFolders);
565   if (num_folders == 0) {
566     /* PONDERME: is this really invalid? */
567     WARN("weird cabinet detect failure: no folders in cabinet\n");
568     if (pmii) {
569       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
570       PFDI_INT(hfdi)->perf->erfType = 0;
571       PFDI_INT(hfdi)->perf->fError = TRUE;
572     }
573     return FALSE;
574   }
575
576   /* get the number of files */
577   num_files = EndGetI16(buf+cfhead_NumFiles);
578   if (num_files == 0) {
579     /* PONDERME: is this really invalid? */
580     WARN("weird cabinet detect failure: no files in cabinet\n");
581     if (pmii) {
582       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
583       PFDI_INT(hfdi)->perf->erfType = 0;
584       PFDI_INT(hfdi)->perf->fError = TRUE;
585     }
586     return FALSE;
587   }
588
589   /* setid */
590   setid = EndGetI16(buf+cfhead_SetID);
591
592   /* cabinet (set) index */
593   cabidx = EndGetI16(buf+cfhead_CabinetIndex);
594
595   /* check the header revision */
596   if ((buf[cfhead_MajorVersion] > 1) ||
597       (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
598   {
599     WARN("cabinet format version > 1.3\n");
600     if (pmii) {
601       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
602       PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
603       PFDI_INT(hfdi)->perf->fError = TRUE;
604     }
605     return FALSE;
606   }
607
608   /* pull the flags out */
609   flags = EndGetI16(buf+cfhead_Flags);
610
611   /* read the reserved-sizes part of header, if present */
612   if (flags & cfheadRESERVE_PRESENT) {
613     if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
614       ERR("bunk reserve-sizes?\n");
615       if (pmii) {
616         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
617         PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
618         PFDI_INT(hfdi)->perf->fError = TRUE;
619       }
620       return FALSE;
621     }
622
623     header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
624     if (pmii) pmii->header_resv = header_resv;
625     folder_resv = buf[cfheadext_FolderReserved];
626     if (pmii) pmii->folder_resv = folder_resv;
627     block_resv  = buf[cfheadext_DataReserved];
628     if (pmii) pmii->block_resv = block_resv;
629
630     if (header_resv > 60000) {
631       WARN("WARNING; header reserved space > 60000\n");
632     }
633
634     /* skip the reserved header */
635     if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
636       ERR("seek failure: header_resv\n");
637       if (pmii) {
638         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
639         PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
640         PFDI_INT(hfdi)->perf->fError = TRUE;
641       }
642       return FALSE;
643     }
644   }
645
646   if (flags & cfheadPREV_CABINET) {
647     prevname = FDI_read_string(hfdi, hf, cabsize);
648     if (!prevname) {
649       if (pmii) {
650         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
651         PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
652         PFDI_INT(hfdi)->perf->fError = TRUE;
653       }
654       return FALSE;
655     } else
656       if (pmii)
657         pmii->prevname = prevname;
658       else
659         PFDI_FREE(hfdi, prevname);
660     previnfo = FDI_read_string(hfdi, hf, cabsize);
661     if (previnfo) {
662       if (pmii) 
663         pmii->previnfo = previnfo;
664       else
665         PFDI_FREE(hfdi, previnfo);
666     }
667   }
668
669   if (flags & cfheadNEXT_CABINET) {
670     if (pmii)
671       pmii->hasnext = TRUE;
672     nextname = FDI_read_string(hfdi, hf, cabsize);
673     if (!nextname) {
674       if ((flags & cfheadPREV_CABINET) && pmii) {
675         if (pmii->prevname) PFDI_FREE(hfdi, prevname);
676         if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
677       }
678       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
679       PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
680       PFDI_INT(hfdi)->perf->fError = TRUE;
681       return FALSE;
682     } else
683       if (pmii)
684         pmii->nextname = nextname;
685       else
686         PFDI_FREE(hfdi, nextname);
687     nextinfo = FDI_read_string(hfdi, hf, cabsize);
688     if (nextinfo) {
689       if (pmii)
690         pmii->nextinfo = nextinfo;
691       else
692         PFDI_FREE(hfdi, nextinfo);
693     }
694   }
695
696   /* we could process the whole cabinet searching for problems;
697      instead lets stop here.  Now let's fill out the paperwork */
698   pfdici->cbCabinet = cabsize;
699   pfdici->cFolders  = num_folders;
700   pfdici->cFiles    = num_files;
701   pfdici->setID     = setid;
702   pfdici->iCabinet  = cabidx;
703   pfdici->fReserve  = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
704   pfdici->hasprev   = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
705   pfdici->hasnext   = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
706   return TRUE;
707 }
708
709 /***********************************************************************
710  *              FDIIsCabinet (CABINET.21)
711  *
712  * Informs the caller as to whether or not the provided file handle is
713  * really a cabinet or not, filling out the provided PFDICABINETINFO
714  * structure with information about the cabinet.  Brief explanations of
715  * the elements of this structure are available as comments accompanying
716  * its definition in wine's include/fdi.h.
717  *
718  * PARAMS
719  *   hfdi   [I]  An HFDI from FDICreate
720  *   hf     [I]  The file handle about which the caller inquires
721  *   pfdici [IO] Pointer to a PFDICABINETINFO structure which will
722  *               be filled out with information about the cabinet
723  *               file indicated by hf if, indeed, it is determined
724  *               to be a cabinet.
725  * 
726  * RETURNS
727  *   TRUE  if the file is a cabinet.  The info pointed to by pfdici will
728  *         be provided.
729  *   FALSE if the file is not a cabinet, or if an error was encountered
730  *         while processing the cabinet.  The PERF structure provided to
731  *         FDICreate can be queried for more error information.
732  *
733  * INCLUDES
734  *   fdi.c
735  */
736 BOOL __cdecl FDIIsCabinet(
737         HFDI            hfdi,
738         INT_PTR         hf,
739         PFDICABINETINFO pfdici)
740 {
741   BOOL rv;
742
743   TRACE("(hfdi == ^%p, hf == ^%ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
744
745   if (!REALLY_IS_FDI(hfdi)) {
746     ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
747     SetLastError(ERROR_INVALID_HANDLE);
748     return FALSE;
749   }
750
751   if (!hf) {
752     ERR("(!hf)!\n");
753     /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
754     PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
755     PFDI_INT(hfdi)->perf->fError = TRUE; */
756     SetLastError(ERROR_INVALID_HANDLE);
757     return FALSE;
758   }
759
760   if (!pfdici) {
761     ERR("(!pfdici)!\n");
762     /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
763     PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
764     PFDI_INT(hfdi)->perf->fError = TRUE; */
765     SetLastError(ERROR_BAD_ARGUMENTS);
766     return FALSE;
767   }
768   rv = FDI_read_entries(hfdi, hf, pfdici, NULL); 
769
770   if (rv)
771     pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
772
773   return rv;
774 }
775
776 /******************************************************************
777  * QTMfdi_initmodel (internal)
778  *
779  * Initialize a model which decodes symbols from [s] to [s]+[n]-1
780  */
781 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
782   int i;
783   m->shiftsleft = 4;
784   m->entries    = n;
785   m->syms       = sym;
786   memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
787   for (i = 0; i < n; i++) {
788     m->tabloc[i+s]     = i;   /* set up a look-up entry for symbol */
789     m->syms[i].sym     = i+s; /* actual symbol */
790     m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
791   }
792   m->syms[n].cumfreq = 0;
793 }
794
795 /******************************************************************
796  * QTMfdi_init (internal)
797  */
798 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
799   unsigned int wndsize = 1 << window;
800   int msz = window * 2, i;
801   cab_ULONG j;
802
803   /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
804   /* if a previously allocated window is big enough, keep it    */
805   if (window < 10 || window > 21) return DECR_DATAFORMAT;
806   if (QTM(actual_size) < wndsize) {
807     if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
808     QTM(window) = NULL;
809   }
810   if (!QTM(window)) {
811     if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
812     QTM(actual_size) = wndsize;
813   }
814   QTM(window_size) = wndsize;
815   QTM(window_posn) = 0;
816
817   /* initialize static slot/extrabits tables */
818   for (i = 0, j = 0; i < 27; i++) {
819     CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
820     CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
821   }
822   for (i = 0, j = 0; i < 42; i++) {
823     CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
824     CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
825   }
826
827   /* initialize arithmetic coding models */
828
829   QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
830
831   QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
832   QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
833   QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
834   QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
835
836   /* model 4 depends on table size, ranges from 20 to 24  */
837   QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
838   /* model 5 depends on table size, ranges from 20 to 36  */
839   QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
840   /* model 6pos depends on table size, ranges from 20 to 42 */
841   QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
842   QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
843
844   return DECR_OK;
845 }
846
847 /************************************************************
848  * LZXfdi_init (internal)
849  */
850 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
851   static const cab_UBYTE bits[]  =
852                         { 0,  0,  0,  0,  1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,
853                           7,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
854                          15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
855                          17, 17, 17};
856   static const cab_ULONG base[] =
857                 {      0,       1,       2,       3,       4,       6,       8,      12,
858                       16,      24,      32,      48,      64,      96,     128,     192,
859                      256,     384,     512,     768,    1024,    1536,    2048,    3072,
860                     4096,    6144,    8192,   12288,   16384,   24576,   32768,   49152,
861                    65536,   98304,  131072,  196608,  262144,  393216,  524288,  655360,
862                   786432,  917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
863                  1835008, 1966080, 2097152};
864   cab_ULONG wndsize = 1 << window;
865   int posn_slots;
866
867   /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
868   /* if a previously allocated window is big enough, keep it     */
869   if (window < 15 || window > 21) return DECR_DATAFORMAT;
870   if (LZX(actual_size) < wndsize) {
871     if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
872     LZX(window) = NULL;
873   }
874   if (!LZX(window)) {
875     if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
876     LZX(actual_size) = wndsize;
877   }
878   LZX(window_size) = wndsize;
879
880   /* initialize static tables */
881   memcpy(CAB(extra_bits), bits, sizeof(bits));
882   memcpy(CAB(lzx_position_base), base, sizeof(base));
883
884   /* calculate required position slots */
885        if (window == 20) posn_slots = 42;
886   else if (window == 21) posn_slots = 50;
887   else posn_slots = window << 1;
888
889   /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
890
891   LZX(R0)  =  LZX(R1)  = LZX(R2) = 1;
892   LZX(main_elements)   = LZX_NUM_CHARS + (posn_slots << 3);
893   LZX(header_read)     = 0;
894   LZX(frames_read)     = 0;
895   LZX(block_remaining) = 0;
896   LZX(block_type)      = LZX_BLOCKTYPE_INVALID;
897   LZX(intel_curpos)    = 0;
898   LZX(intel_started)   = 0;
899   LZX(window_posn)     = 0;
900
901   /* initialize tables to 0 (because deltas will be applied to them) */
902   memset(LZX(MAINTREE_len), 0, sizeof(LZX(MAINTREE_len)));
903   memset(LZX(LENGTH_len), 0, sizeof(LZX(LENGTH_len)));
904
905   return DECR_OK;
906 }
907
908 /****************************************************
909  * NONEfdi_decomp(internal)
910  */
911 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
912 {
913   if (inlen != outlen) return DECR_ILLEGALDATA;
914   memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
915   return DECR_OK;
916 }
917
918 /********************************************************
919  * Ziphuft_free (internal)
920  */
921 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
922 {
923   register struct Ziphuft *p, *q;
924
925   /* Go through linked list, freeing from the allocated (t[-1]) address. */
926   p = t;
927   while (p != (struct Ziphuft *)NULL)
928   {
929     q = (--p)->v.t;
930     PFDI_FREE(hfdi, p);
931     p = q;
932   } 
933 }
934
935 /*********************************************************
936  * fdi_Ziphuft_build (internal)
937  */
938 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, const cab_UWORD *d, const cab_UWORD *e,
939 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
940 {
941   cab_ULONG a;                          /* counter for codes of length k */
942   cab_ULONG el;                         /* length of EOB code (value 256) */
943   cab_ULONG f;                          /* i repeats in table every f entries */
944   cab_LONG g;                           /* maximum code length */
945   cab_LONG h;                           /* table level */
946   register cab_ULONG i;                 /* counter, current code */
947   register cab_ULONG j;                 /* counter */
948   register cab_LONG k;                  /* number of bits in current code */
949   cab_LONG *l;                          /* stack of bits per table */
950   register cab_ULONG *p;                /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
951   register struct Ziphuft *q;           /* points to current table */
952   struct Ziphuft r;                     /* table entry for structure assignment */
953   register cab_LONG w;                  /* bits before this table == (l * h) */
954   cab_ULONG *xp;                        /* pointer into x */
955   cab_LONG y;                           /* number of dummy codes added */
956   cab_ULONG z;                          /* number of entries in current table */
957
958   l = ZIP(lx)+1;
959
960   /* Generate counts for each bit length */
961   el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
962
963   for(i = 0; i < ZIPBMAX+1; ++i)
964     ZIP(c)[i] = 0;
965   p = b;  i = n;
966   do
967   {
968     ZIP(c)[*p]++; p++;               /* assume all entries <= ZIPBMAX */
969   } while (--i);
970   if (ZIP(c)[0] == n)                /* null input--all zero length codes */
971   {
972     *t = (struct Ziphuft *)NULL;
973     *m = 0;
974     return 0;
975   }
976
977   /* Find minimum and maximum length, bound *m by those */
978   for (j = 1; j <= ZIPBMAX; j++)
979     if (ZIP(c)[j])
980       break;
981   k = j;                        /* minimum code length */
982   if ((cab_ULONG)*m < j)
983     *m = j;
984   for (i = ZIPBMAX; i; i--)
985     if (ZIP(c)[i])
986       break;
987   g = i;                        /* maximum code length */
988   if ((cab_ULONG)*m > i)
989     *m = i;
990
991   /* Adjust last length count to fill out codes, if needed */
992   for (y = 1 << j; j < i; j++, y <<= 1)
993     if ((y -= ZIP(c)[j]) < 0)
994       return 2;                 /* bad input: more codes than bits */
995   if ((y -= ZIP(c)[i]) < 0)
996     return 2;
997   ZIP(c)[i] += y;
998
999   /* Generate starting offsets LONGo the value table for each length */
1000   ZIP(x)[1] = j = 0;
1001   p = ZIP(c) + 1;  xp = ZIP(x) + 2;
1002   while (--i)
1003   {                 /* note that i == g from above */
1004     *xp++ = (j += *p++);
1005   }
1006
1007   /* Make a table of values in order of bit lengths */
1008   p = b;  i = 0;
1009   do{
1010     if ((j = *p++) != 0)
1011       ZIP(v)[ZIP(x)[j]++] = i;
1012   } while (++i < n);
1013
1014
1015   /* Generate the Huffman codes and for each, make the table entries */
1016   ZIP(x)[0] = i = 0;                 /* first Huffman code is zero */
1017   p = ZIP(v);                        /* grab values in bit order */
1018   h = -1;                       /* no tables yet--level -1 */
1019   w = l[-1] = 0;                /* no bits decoded yet */
1020   ZIP(u)[0] = (struct Ziphuft *)NULL;   /* just to keep compilers happy */
1021   q = (struct Ziphuft *)NULL;      /* ditto */
1022   z = 0;                        /* ditto */
1023
1024   /* go through the bit lengths (k already is bits in shortest code) */
1025   for (; k <= g; k++)
1026   {
1027     a = ZIP(c)[k];
1028     while (a--)
1029     {
1030       /* here i is the Huffman code of length k bits for value *p */
1031       /* make tables up to required level */
1032       while (k > w + l[h])
1033       {
1034         w += l[h++];            /* add bits already decoded */
1035
1036         /* compute minimum size table less than or equal to *m bits */
1037         z = (z = g - w) > (cab_ULONG)*m ? *m : z;        /* upper limit */
1038         if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
1039         {                       /* too few codes for k-w bit table */
1040           f -= a + 1;           /* deduct codes from patterns left */
1041           xp = ZIP(c) + k;
1042           while (++j < z)       /* try smaller tables up to z bits */
1043           {
1044             if ((f <<= 1) <= *++xp)
1045               break;            /* enough codes to use up j bits */
1046             f -= *xp;           /* else deduct codes from patterns */
1047           }
1048         }
1049         if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
1050           j = el - w;           /* make EOB code end at table */
1051         z = 1 << j;             /* table entries for j-bit table */
1052         l[h] = j;               /* set table size in stack */
1053
1054         /* allocate and link in new table */
1055         if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
1056         {
1057           if(h)
1058             fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
1059           return 3;             /* not enough memory */
1060         }
1061         *t = q + 1;             /* link to list for Ziphuft_free() */
1062         *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
1063         ZIP(u)[h] = ++q;             /* table starts after link */
1064
1065         /* connect to last table, if there is one */
1066         if (h)
1067         {
1068           ZIP(x)[h] = i;              /* save pattern for backing up */
1069           r.b = (cab_UBYTE)l[h-1];    /* bits to dump before this table */
1070           r.e = (cab_UBYTE)(16 + j);  /* bits in this table */
1071           r.v.t = q;                  /* pointer to this table */
1072           j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
1073           ZIP(u)[h-1][j] = r;        /* connect to last table */
1074         }
1075       }
1076
1077       /* set up table entry in r */
1078       r.b = (cab_UBYTE)(k - w);
1079       if (p >= ZIP(v) + n)
1080         r.e = 99;               /* out of values--invalid code */
1081       else if (*p < s)
1082       {
1083         r.e = (cab_UBYTE)(*p < 256 ? 16 : 15);    /* 256 is end-of-block code */
1084         r.v.n = *p++;           /* simple code is just the value */
1085       }
1086       else
1087       {
1088         r.e = (cab_UBYTE)e[*p - s];   /* non-simple--look up in lists */
1089         r.v.n = d[*p++ - s];
1090       }
1091
1092       /* fill code-like entries with r */
1093       f = 1 << (k - w);
1094       for (j = i >> w; j < z; j += f)
1095         q[j] = r;
1096
1097       /* backwards increment the k-bit code i */
1098       for (j = 1 << (k - 1); i & j; j >>= 1)
1099         i ^= j;
1100       i ^= j;
1101
1102       /* backup over finished tables */
1103       while ((i & ((1 << w) - 1)) != ZIP(x)[h])
1104         w -= l[--h];            /* don't need to update q */
1105     }
1106   }
1107
1108   /* return actual size of base table */
1109   *m = l[0];
1110
1111   /* Return true (1) if we were given an incomplete table */
1112   return y != 0 && g != 1;
1113 }
1114
1115 /*********************************************************
1116  * fdi_Zipinflate_codes (internal)
1117  */
1118 static cab_LONG fdi_Zipinflate_codes(const struct Ziphuft *tl, const struct Ziphuft *td,
1119   cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
1120 {
1121   register cab_ULONG e;     /* table entry flag/number of extra bits */
1122   cab_ULONG n, d;           /* length and index for copy */
1123   cab_ULONG w;              /* current window position */
1124   const struct Ziphuft *t;  /* pointer to table entry */
1125   cab_ULONG ml, md;         /* masks for bl and bd bits */
1126   register cab_ULONG b;     /* bit buffer */
1127   register cab_ULONG k;     /* number of bits in bit buffer */
1128
1129   /* make local copies of globals */
1130   b = ZIP(bb);                       /* initialize bit buffer */
1131   k = ZIP(bk);
1132   w = ZIP(window_posn);                       /* initialize window position */
1133
1134   /* inflate the coded data */
1135   ml = Zipmask[bl];             /* precompute masks for speed */
1136   md = Zipmask[bd];
1137
1138   for(;;)
1139   {
1140     ZIPNEEDBITS((cab_ULONG)bl)
1141     if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16)
1142       do
1143       {
1144         if (e == 99)
1145           return 1;
1146         ZIPDUMPBITS(t->b)
1147         e -= 16;
1148         ZIPNEEDBITS(e)
1149       } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
1150     ZIPDUMPBITS(t->b)
1151     if (e == 16)                /* then it's a literal */
1152       CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
1153     else                        /* it's an EOB or a length */
1154     {
1155       /* exit if end of block */
1156       if(e == 15)
1157         break;
1158
1159       /* get length of block to copy */
1160       ZIPNEEDBITS(e)
1161       n = t->v.n + ((cab_ULONG)b & Zipmask[e]);
1162       ZIPDUMPBITS(e);
1163
1164       /* decode distance of block to copy */
1165       ZIPNEEDBITS((cab_ULONG)bd)
1166       if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16)
1167         do {
1168           if (e == 99)
1169             return 1;
1170           ZIPDUMPBITS(t->b)
1171           e -= 16;
1172           ZIPNEEDBITS(e)
1173         } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
1174       ZIPDUMPBITS(t->b)
1175       ZIPNEEDBITS(e)
1176       d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]);
1177       ZIPDUMPBITS(e)
1178       do
1179       {
1180         n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
1181         do
1182         {
1183           CAB(outbuf)[w++] = CAB(outbuf)[d++];
1184         } while (--e);
1185       } while (n);
1186     }
1187   }
1188
1189   /* restore the globals from the locals */
1190   ZIP(window_posn) = w;              /* restore global window pointer */
1191   ZIP(bb) = b;                       /* restore global bit buffer */
1192   ZIP(bk) = k;
1193
1194   /* done */
1195   return 0;
1196 }
1197
1198 /***********************************************************
1199  * Zipinflate_stored (internal)
1200  */
1201 static cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1202 /* "decompress" an inflated type 0 (stored) block. */
1203 {
1204   cab_ULONG n;           /* number of bytes in block */
1205   cab_ULONG w;           /* current window position */
1206   register cab_ULONG b;  /* bit buffer */
1207   register cab_ULONG k;  /* number of bits in bit buffer */
1208
1209   /* make local copies of globals */
1210   b = ZIP(bb);                       /* initialize bit buffer */
1211   k = ZIP(bk);
1212   w = ZIP(window_posn);              /* initialize window position */
1213
1214   /* go to byte boundary */
1215   n = k & 7;
1216   ZIPDUMPBITS(n);
1217
1218   /* get the length and its complement */
1219   ZIPNEEDBITS(16)
1220   n = ((cab_ULONG)b & 0xffff);
1221   ZIPDUMPBITS(16)
1222   ZIPNEEDBITS(16)
1223   if (n != (cab_ULONG)((~b) & 0xffff))
1224     return 1;                   /* error in compressed data */
1225   ZIPDUMPBITS(16)
1226
1227   /* read and output the compressed data */
1228   while(n--)
1229   {
1230     ZIPNEEDBITS(8)
1231     CAB(outbuf)[w++] = (cab_UBYTE)b;
1232     ZIPDUMPBITS(8)
1233   }
1234
1235   /* restore the globals from the locals */
1236   ZIP(window_posn) = w;              /* restore global window pointer */
1237   ZIP(bb) = b;                       /* restore global bit buffer */
1238   ZIP(bk) = k;
1239   return 0;
1240 }
1241
1242 /******************************************************
1243  * fdi_Zipinflate_fixed (internal)
1244  */
1245 static cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1246 {
1247   struct Ziphuft *fixed_tl;
1248   struct Ziphuft *fixed_td;
1249   cab_LONG fixed_bl, fixed_bd;
1250   cab_LONG i;                /* temporary variable */
1251   cab_ULONG *l;
1252
1253   l = ZIP(ll);
1254
1255   /* literal table */
1256   for(i = 0; i < 144; i++)
1257     l[i] = 8;
1258   for(; i < 256; i++)
1259     l[i] = 9;
1260   for(; i < 280; i++)
1261     l[i] = 7;
1262   for(; i < 288; i++)          /* make a complete, but wrong code set */
1263     l[i] = 8;
1264   fixed_bl = 7;
1265   if((i = fdi_Ziphuft_build(l, 288, 257, Zipcplens, Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1266     return i;
1267
1268   /* distance table */
1269   for(i = 0; i < 30; i++)      /* make an incomplete code set */
1270     l[i] = 5;
1271   fixed_bd = 5;
1272   if((i = fdi_Ziphuft_build(l, 30, 0, Zipcpdist, Zipcpdext, &fixed_td, &fixed_bd, decomp_state)) > 1)
1273   {
1274     fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1275     return i;
1276   }
1277
1278   /* decompress until an end-of-block code */
1279   i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1280
1281   fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1282   fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1283   return i;
1284 }
1285
1286 /**************************************************************
1287  * fdi_Zipinflate_dynamic (internal)
1288  */
1289 static cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1290  /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1291 {
1292   cab_LONG i;           /* temporary variables */
1293   cab_ULONG j;
1294   cab_ULONG *ll;
1295   cab_ULONG l;                  /* last length */
1296   cab_ULONG m;                  /* mask for bit lengths table */
1297   cab_ULONG n;                  /* number of lengths to get */
1298   struct Ziphuft *tl;           /* literal/length code table */
1299   struct Ziphuft *td;           /* distance code table */
1300   cab_LONG bl;                  /* lookup bits for tl */
1301   cab_LONG bd;                  /* lookup bits for td */
1302   cab_ULONG nb;                 /* number of bit length codes */
1303   cab_ULONG nl;                 /* number of literal/length codes */
1304   cab_ULONG nd;                 /* number of distance codes */
1305   register cab_ULONG b;         /* bit buffer */
1306   register cab_ULONG k;         /* number of bits in bit buffer */
1307
1308   /* make local bit buffer */
1309   b = ZIP(bb);
1310   k = ZIP(bk);
1311   ll = ZIP(ll);
1312
1313   /* read in table lengths */
1314   ZIPNEEDBITS(5)
1315   nl = 257 + ((cab_ULONG)b & 0x1f);      /* number of literal/length codes */
1316   ZIPDUMPBITS(5)
1317   ZIPNEEDBITS(5)
1318   nd = 1 + ((cab_ULONG)b & 0x1f);        /* number of distance codes */
1319   ZIPDUMPBITS(5)
1320   ZIPNEEDBITS(4)
1321   nb = 4 + ((cab_ULONG)b & 0xf);         /* number of bit length codes */
1322   ZIPDUMPBITS(4)
1323   if(nl > 288 || nd > 32)
1324     return 1;                   /* bad lengths */
1325
1326   /* read in bit-length-code lengths */
1327   for(j = 0; j < nb; j++)
1328   {
1329     ZIPNEEDBITS(3)
1330     ll[Zipborder[j]] = (cab_ULONG)b & 7;
1331     ZIPDUMPBITS(3)
1332   }
1333   for(; j < 19; j++)
1334     ll[Zipborder[j]] = 0;
1335
1336   /* build decoding table for trees--single level, 7 bit lookup */
1337   bl = 7;
1338   if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1339   {
1340     if(i == 1)
1341       fdi_Ziphuft_free(CAB(hfdi), tl);
1342     return i;                   /* incomplete code set */
1343   }
1344
1345   /* read in literal and distance code lengths */
1346   n = nl + nd;
1347   m = Zipmask[bl];
1348   i = l = 0;
1349   while((cab_ULONG)i < n)
1350   {
1351     ZIPNEEDBITS((cab_ULONG)bl)
1352     j = (td = tl + ((cab_ULONG)b & m))->b;
1353     ZIPDUMPBITS(j)
1354     j = td->v.n;
1355     if (j < 16)                 /* length of code in bits (0..15) */
1356       ll[i++] = l = j;          /* save last length in l */
1357     else if (j == 16)           /* repeat last length 3 to 6 times */
1358     {
1359       ZIPNEEDBITS(2)
1360       j = 3 + ((cab_ULONG)b & 3);
1361       ZIPDUMPBITS(2)
1362       if((cab_ULONG)i + j > n)
1363         return 1;
1364       while (j--)
1365         ll[i++] = l;
1366     }
1367     else if (j == 17)           /* 3 to 10 zero length codes */
1368     {
1369       ZIPNEEDBITS(3)
1370       j = 3 + ((cab_ULONG)b & 7);
1371       ZIPDUMPBITS(3)
1372       if ((cab_ULONG)i + j > n)
1373         return 1;
1374       while (j--)
1375         ll[i++] = 0;
1376       l = 0;
1377     }
1378     else                        /* j == 18: 11 to 138 zero length codes */
1379     {
1380       ZIPNEEDBITS(7)
1381       j = 11 + ((cab_ULONG)b & 0x7f);
1382       ZIPDUMPBITS(7)
1383       if ((cab_ULONG)i + j > n)
1384         return 1;
1385       while (j--)
1386         ll[i++] = 0;
1387       l = 0;
1388     }
1389   }
1390
1391   /* free decoding table for trees */
1392   fdi_Ziphuft_free(CAB(hfdi), tl);
1393
1394   /* restore the global bit buffer */
1395   ZIP(bb) = b;
1396   ZIP(bk) = k;
1397
1398   /* build the decoding tables for literal/length and distance codes */
1399   bl = ZIPLBITS;
1400   if((i = fdi_Ziphuft_build(ll, nl, 257, Zipcplens, Zipcplext, &tl, &bl, decomp_state)) != 0)
1401   {
1402     if(i == 1)
1403       fdi_Ziphuft_free(CAB(hfdi), tl);
1404     return i;                   /* incomplete code set */
1405   }
1406   bd = ZIPDBITS;
1407   fdi_Ziphuft_build(ll + nl, nd, 0, Zipcpdist, Zipcpdext, &td, &bd, decomp_state);
1408
1409   /* decompress until an end-of-block code */
1410   if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1411     return 1;
1412
1413   /* free the decoding tables, return */
1414   fdi_Ziphuft_free(CAB(hfdi), tl);
1415   fdi_Ziphuft_free(CAB(hfdi), td);
1416   return 0;
1417 }
1418
1419 /*****************************************************
1420  * fdi_Zipinflate_block (internal)
1421  */
1422 static cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1423 { /* decompress an inflated block */
1424   cab_ULONG t;                  /* block type */
1425   register cab_ULONG b;     /* bit buffer */
1426   register cab_ULONG k;     /* number of bits in bit buffer */
1427
1428   /* make local bit buffer */
1429   b = ZIP(bb);
1430   k = ZIP(bk);
1431
1432   /* read in last block bit */
1433   ZIPNEEDBITS(1)
1434   *e = (cab_LONG)b & 1;
1435   ZIPDUMPBITS(1)
1436
1437   /* read in block type */
1438   ZIPNEEDBITS(2)
1439   t = (cab_ULONG)b & 3;
1440   ZIPDUMPBITS(2)
1441
1442   /* restore the global bit buffer */
1443   ZIP(bb) = b;
1444   ZIP(bk) = k;
1445
1446   /* inflate that block type */
1447   if(t == 2)
1448     return fdi_Zipinflate_dynamic(decomp_state);
1449   if(t == 0)
1450     return fdi_Zipinflate_stored(decomp_state);
1451   if(t == 1)
1452     return fdi_Zipinflate_fixed(decomp_state);
1453   /* bad block type */
1454   return 2;
1455 }
1456
1457 /****************************************************
1458  * ZIPfdi_decomp(internal)
1459  */
1460 static int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1461 {
1462   cab_LONG e;               /* last block flag */
1463
1464   TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1465
1466   ZIP(inpos) = CAB(inbuf);
1467   ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1468   if(outlen > ZIPWSIZE)
1469     return DECR_DATAFORMAT;
1470
1471   /* CK = Chris Kirmse, official Microsoft purloiner */
1472   if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1473     return DECR_ILLEGALDATA;
1474   ZIP(inpos) += 2;
1475
1476   do {
1477     if(fdi_Zipinflate_block(&e, decomp_state))
1478       return DECR_ILLEGALDATA;
1479   } while(!e);
1480
1481   /* return success */
1482   return DECR_OK;
1483 }
1484
1485 /*******************************************************************
1486  * QTMfdi_decomp(internal)
1487  */
1488 static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1489 {
1490   cab_UBYTE *inpos  = CAB(inbuf);
1491   cab_UBYTE *window = QTM(window);
1492   cab_UBYTE *runsrc, *rundest;
1493   cab_ULONG window_posn = QTM(window_posn);
1494   cab_ULONG window_size = QTM(window_size);
1495
1496   /* used by bitstream macros */
1497   register int bitsleft, bitrun, bitsneed;
1498   register cab_ULONG bitbuf;
1499
1500   /* used by GET_SYMBOL */
1501   cab_ULONG range;
1502   cab_UWORD symf;
1503   int i;
1504
1505   int extra, togo = outlen, match_length = 0, copy_length;
1506   cab_UBYTE selector, sym;
1507   cab_ULONG match_offset = 0;
1508
1509   cab_UWORD H = 0xFFFF, L = 0, C;
1510
1511   TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1512
1513   /* read initial value of C */
1514   Q_INIT_BITSTREAM;
1515   Q_READ_BITS(C, 16);
1516
1517   /* apply 2^x-1 mask */
1518   window_posn &= window_size - 1;
1519   /* runs can't straddle the window wraparound */
1520   if ((window_posn + togo) > window_size) {
1521     TRACE("straddled run\n");
1522     return DECR_DATAFORMAT;
1523   }
1524
1525   while (togo > 0) {
1526     GET_SYMBOL(model7, selector);
1527     switch (selector) {
1528     case 0:
1529       GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1530       break;
1531     case 1:
1532       GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1533       break;
1534     case 2:
1535       GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1536       break;
1537     case 3:
1538       GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1539       break;
1540
1541     case 4:
1542       /* selector 4 = fixed length of 3 */
1543       GET_SYMBOL(model4, sym);
1544       Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1545       match_offset = CAB(q_position_base)[sym] + extra + 1;
1546       match_length = 3;
1547       break;
1548
1549     case 5:
1550       /* selector 5 = fixed length of 4 */
1551       GET_SYMBOL(model5, sym);
1552       Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1553       match_offset = CAB(q_position_base)[sym] + extra + 1;
1554       match_length = 4;
1555       break;
1556
1557     case 6:
1558       /* selector 6 = variable length */
1559       GET_SYMBOL(model6len, sym);
1560       Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1561       match_length = CAB(q_length_base)[sym] + extra + 5;
1562       GET_SYMBOL(model6pos, sym);
1563       Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1564       match_offset = CAB(q_position_base)[sym] + extra + 1;
1565       break;
1566
1567     default:
1568       TRACE("Selector is bogus\n");
1569       return DECR_ILLEGALDATA;
1570     }
1571
1572     /* if this is a match */
1573     if (selector >= 4) {
1574       rundest = window + window_posn;
1575       togo -= match_length;
1576
1577       /* copy any wrapped around source data */
1578       if (window_posn >= match_offset) {
1579         /* no wrap */
1580         runsrc = rundest - match_offset;
1581       } else {
1582         runsrc = rundest + (window_size - match_offset);
1583         copy_length = match_offset - window_posn;
1584         if (copy_length < match_length) {
1585           match_length -= copy_length;
1586           window_posn += copy_length;
1587           while (copy_length-- > 0) *rundest++ = *runsrc++;
1588           runsrc = window;
1589         }
1590       }
1591       window_posn += match_length;
1592
1593       /* copy match data - no worries about destination wraps */
1594       while (match_length-- > 0) *rundest++ = *runsrc++;
1595     }
1596   } /* while (togo > 0) */
1597
1598   if (togo != 0) {
1599     TRACE("Frame overflow, this_run = %d\n", togo);
1600     return DECR_ILLEGALDATA;
1601   }
1602
1603   memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1604     outlen, outlen);
1605
1606   QTM(window_posn) = window_posn;
1607   return DECR_OK;
1608 }
1609
1610 /************************************************************
1611  * fdi_lzx_read_lens (internal)
1612  */
1613 static int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1614                   fdi_decomp_state *decomp_state) {
1615   cab_ULONG i,j, x,y;
1616   int z;
1617
1618   register cab_ULONG bitbuf = lb->bb;
1619   register int bitsleft = lb->bl;
1620   cab_UBYTE *inpos = lb->ip;
1621   cab_UWORD *hufftbl;
1622   
1623   for (x = 0; x < 20; x++) {
1624     READ_BITS(y, 4);
1625     LENTABLE(PRETREE)[x] = y;
1626   }
1627   BUILD_TABLE(PRETREE);
1628
1629   for (x = first; x < last; ) {
1630     READ_HUFFSYM(PRETREE, z);
1631     if (z == 17) {
1632       READ_BITS(y, 4); y += 4;
1633       while (y--) lens[x++] = 0;
1634     }
1635     else if (z == 18) {
1636       READ_BITS(y, 5); y += 20;
1637       while (y--) lens[x++] = 0;
1638     }
1639     else if (z == 19) {
1640       READ_BITS(y, 1); y += 4;
1641       READ_HUFFSYM(PRETREE, z);
1642       z = lens[x] - z; if (z < 0) z += 17;
1643       while (y--) lens[x++] = z;
1644     }
1645     else {
1646       z = lens[x] - z; if (z < 0) z += 17;
1647       lens[x++] = z;
1648     }
1649   }
1650
1651   lb->bb = bitbuf;
1652   lb->bl = bitsleft;
1653   lb->ip = inpos;
1654   return 0;
1655 }
1656
1657 /*******************************************************
1658  * LZXfdi_decomp(internal)
1659  */
1660 static int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1661   cab_UBYTE *inpos  = CAB(inbuf);
1662   const cab_UBYTE *endinp = inpos + inlen;
1663   cab_UBYTE *window = LZX(window);
1664   cab_UBYTE *runsrc, *rundest;
1665   cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1666
1667   cab_ULONG window_posn = LZX(window_posn);
1668   cab_ULONG window_size = LZX(window_size);
1669   cab_ULONG R0 = LZX(R0);
1670   cab_ULONG R1 = LZX(R1);
1671   cab_ULONG R2 = LZX(R2);
1672
1673   register cab_ULONG bitbuf;
1674   register int bitsleft;
1675   cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1676   struct lzx_bits lb; /* used in READ_LENGTHS macro */
1677
1678   int togo = outlen, this_run, main_element, aligned_bits;
1679   int match_length, copy_length, length_footer, extra, verbatim_bits;
1680
1681   TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1682
1683   INIT_BITSTREAM;
1684
1685   /* read header if necessary */
1686   if (!LZX(header_read)) {
1687     i = j = 0;
1688     READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1689     LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1690     LZX(header_read) = 1;
1691   }
1692
1693   /* main decoding loop */
1694   while (togo > 0) {
1695     /* last block finished, new block expected */
1696     if (LZX(block_remaining) == 0) {
1697       if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1698         if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1699         INIT_BITSTREAM;
1700       }
1701
1702       READ_BITS(LZX(block_type), 3);
1703       READ_BITS(i, 16);
1704       READ_BITS(j, 8);
1705       LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1706
1707       switch (LZX(block_type)) {
1708       case LZX_BLOCKTYPE_ALIGNED:
1709         for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1710         BUILD_TABLE(ALIGNED);
1711         /* rest of aligned header is same as verbatim */
1712
1713       case LZX_BLOCKTYPE_VERBATIM:
1714         READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1715         READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1716         BUILD_TABLE(MAINTREE);
1717         if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1718
1719         READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1720         BUILD_TABLE(LENGTH);
1721         break;
1722
1723       case LZX_BLOCKTYPE_UNCOMPRESSED:
1724         LZX(intel_started) = 1; /* because we can't assume otherwise */
1725         ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1726         if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1727         R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1728         R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1729         R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1730         break;
1731
1732       default:
1733         return DECR_ILLEGALDATA;
1734       }
1735     }
1736
1737     /* buffer exhaustion check */
1738     if (inpos > endinp) {
1739       /* it's possible to have a file where the next run is less than
1740        * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1741        * in building the tables will exhaust the buffer, so we should
1742        * allow for this, but not allow those accidentally read bits to
1743        * be used (so we check that there are at least 16 bits
1744        * remaining - in this boundary case they aren't really part of
1745        * the compressed data)
1746        */
1747       if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1748     }
1749
1750     while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1751       if (this_run > togo) this_run = togo;
1752       togo -= this_run;
1753       LZX(block_remaining) -= this_run;
1754
1755       /* apply 2^x-1 mask */
1756       window_posn &= window_size - 1;
1757       /* runs can't straddle the window wraparound */
1758       if ((window_posn + this_run) > window_size)
1759         return DECR_DATAFORMAT;
1760
1761       switch (LZX(block_type)) {
1762
1763       case LZX_BLOCKTYPE_VERBATIM:
1764         while (this_run > 0) {
1765           READ_HUFFSYM(MAINTREE, main_element);
1766
1767           if (main_element < LZX_NUM_CHARS) {
1768             /* literal: 0 to LZX_NUM_CHARS-1 */
1769             window[window_posn++] = main_element;
1770             this_run--;
1771           }
1772           else {
1773             /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1774             main_element -= LZX_NUM_CHARS;
1775   
1776             match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1777             if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1778               READ_HUFFSYM(LENGTH, length_footer);
1779               match_length += length_footer;
1780             }
1781             match_length += LZX_MIN_MATCH;
1782   
1783             match_offset = main_element >> 3;
1784   
1785             if (match_offset > 2) {
1786               /* not repeated offset */
1787               if (match_offset != 3) {
1788                 extra = CAB(extra_bits)[match_offset];
1789                 READ_BITS(verbatim_bits, extra);
1790                 match_offset = CAB(lzx_position_base)[match_offset] 
1791                                - 2 + verbatim_bits;
1792               }
1793               else {
1794                 match_offset = 1;
1795               }
1796   
1797               /* update repeated offset LRU queue */
1798               R2 = R1; R1 = R0; R0 = match_offset;
1799             }
1800             else if (match_offset == 0) {
1801               match_offset = R0;
1802             }
1803             else if (match_offset == 1) {
1804               match_offset = R1;
1805               R1 = R0; R0 = match_offset;
1806             }
1807             else /* match_offset == 2 */ {
1808               match_offset = R2;
1809               R2 = R0; R0 = match_offset;
1810             }
1811
1812             rundest = window + window_posn;
1813             this_run -= match_length;
1814
1815             /* copy any wrapped around source data */
1816             if (window_posn >= match_offset) {
1817               /* no wrap */
1818               runsrc = rundest - match_offset;
1819             } else {
1820               runsrc = rundest + (window_size - match_offset);
1821               copy_length = match_offset - window_posn;
1822               if (copy_length < match_length) {
1823                 match_length -= copy_length;
1824                 window_posn += copy_length;
1825                 while (copy_length-- > 0) *rundest++ = *runsrc++;
1826                 runsrc = window;
1827               }
1828             }
1829             window_posn += match_length;
1830
1831             /* copy match data - no worries about destination wraps */
1832             while (match_length-- > 0) *rundest++ = *runsrc++;
1833           }
1834         }
1835         break;
1836
1837       case LZX_BLOCKTYPE_ALIGNED:
1838         while (this_run > 0) {
1839           READ_HUFFSYM(MAINTREE, main_element);
1840   
1841           if (main_element < LZX_NUM_CHARS) {
1842             /* literal: 0 to LZX_NUM_CHARS-1 */
1843             window[window_posn++] = main_element;
1844             this_run--;
1845           }
1846           else {
1847             /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1848             main_element -= LZX_NUM_CHARS;
1849   
1850             match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1851             if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1852               READ_HUFFSYM(LENGTH, length_footer);
1853               match_length += length_footer;
1854             }
1855             match_length += LZX_MIN_MATCH;
1856   
1857             match_offset = main_element >> 3;
1858   
1859             if (match_offset > 2) {
1860               /* not repeated offset */
1861               extra = CAB(extra_bits)[match_offset];
1862               match_offset = CAB(lzx_position_base)[match_offset] - 2;
1863               if (extra > 3) {
1864                 /* verbatim and aligned bits */
1865                 extra -= 3;
1866                 READ_BITS(verbatim_bits, extra);
1867                 match_offset += (verbatim_bits << 3);
1868                 READ_HUFFSYM(ALIGNED, aligned_bits);
1869                 match_offset += aligned_bits;
1870               }
1871               else if (extra == 3) {
1872                 /* aligned bits only */
1873                 READ_HUFFSYM(ALIGNED, aligned_bits);
1874                 match_offset += aligned_bits;
1875               }
1876               else if (extra > 0) { /* extra==1, extra==2 */
1877                 /* verbatim bits only */
1878                 READ_BITS(verbatim_bits, extra);
1879                 match_offset += verbatim_bits;
1880               }
1881               else /* extra == 0 */ {
1882                 /* ??? */
1883                 match_offset = 1;
1884               }
1885   
1886               /* update repeated offset LRU queue */
1887               R2 = R1; R1 = R0; R0 = match_offset;
1888             }
1889             else if (match_offset == 0) {
1890               match_offset = R0;
1891             }
1892             else if (match_offset == 1) {
1893               match_offset = R1;
1894               R1 = R0; R0 = match_offset;
1895             }
1896             else /* match_offset == 2 */ {
1897               match_offset = R2;
1898               R2 = R0; R0 = match_offset;
1899             }
1900
1901             rundest = window + window_posn;
1902             this_run -= match_length;
1903
1904             /* copy any wrapped around source data */
1905             if (window_posn >= match_offset) {
1906               /* no wrap */
1907               runsrc = rundest - match_offset;
1908             } else {
1909               runsrc = rundest + (window_size - match_offset);
1910               copy_length = match_offset - window_posn;
1911               if (copy_length < match_length) {
1912                 match_length -= copy_length;
1913                 window_posn += copy_length;
1914                 while (copy_length-- > 0) *rundest++ = *runsrc++;
1915                 runsrc = window;
1916               }
1917             }
1918             window_posn += match_length;
1919
1920             /* copy match data - no worries about destination wraps */
1921             while (match_length-- > 0) *rundest++ = *runsrc++;
1922           }
1923         }
1924         break;
1925
1926       case LZX_BLOCKTYPE_UNCOMPRESSED:
1927         if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1928         memcpy(window + window_posn, inpos, (size_t) this_run);
1929         inpos += this_run; window_posn += this_run;
1930         break;
1931
1932       default:
1933         return DECR_ILLEGALDATA; /* might as well */
1934       }
1935
1936     }
1937   }
1938
1939   if (togo != 0) return DECR_ILLEGALDATA;
1940   memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1941     outlen, (size_t) outlen);
1942
1943   LZX(window_posn) = window_posn;
1944   LZX(R0) = R0;
1945   LZX(R1) = R1;
1946   LZX(R2) = R2;
1947
1948   /* intel E8 decoding */
1949   if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1950     if (outlen <= 6 || !LZX(intel_started)) {
1951       LZX(intel_curpos) += outlen;
1952     }
1953     else {
1954       cab_UBYTE *data    = CAB(outbuf);
1955       cab_UBYTE *dataend = data + outlen - 10;
1956       cab_LONG curpos    = LZX(intel_curpos);
1957       cab_LONG filesize  = LZX(intel_filesize);
1958       cab_LONG abs_off, rel_off;
1959
1960       LZX(intel_curpos) = curpos + outlen;
1961
1962       while (data < dataend) {
1963         if (*data++ != 0xE8) { curpos++; continue; }
1964         abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1965         if ((abs_off >= -curpos) && (abs_off < filesize)) {
1966           rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1967           data[0] = (cab_UBYTE) rel_off;
1968           data[1] = (cab_UBYTE) (rel_off >> 8);
1969           data[2] = (cab_UBYTE) (rel_off >> 16);
1970           data[3] = (cab_UBYTE) (rel_off >> 24);
1971         }
1972         data += 4;
1973         curpos += 5;
1974       }
1975     }
1976   }
1977   return DECR_OK;
1978 }
1979
1980 /**********************************************************
1981  * fdi_decomp (internal)
1982  *
1983  * Decompress the requested number of bytes.  If savemode is zero,
1984  * do not save the output anywhere, just plow through blocks until we
1985  * reach the specified (uncompressed) distance from the starting point,
1986  * and remember the position of the cabfile pointer (and which cabfile)
1987  * after we are done; otherwise, save the data out to CAB(filehf),
1988  * decompressing the requested number of bytes and writing them out.  This
1989  * is also where we jump to additional cabinets in the case of split
1990  * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1991  */
1992 static int fdi_decomp(const struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
1993   char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
1994 {
1995   cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
1996   cab_UBYTE buf[cfdata_SIZEOF], *data;
1997   cab_UWORD inlen, len, outlen, cando;
1998   cab_ULONG cksum;
1999   cab_LONG err;
2000   fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
2001
2002   TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
2003
2004   while (bytes > 0) {
2005     /* cando = the max number of bytes we can do */
2006     cando = CAB(outlen);
2007     if (cando > bytes) cando = bytes;
2008
2009     /* if cando != 0 */
2010     if (cando && savemode)
2011       PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
2012
2013     CAB(outpos) += cando;
2014     CAB(outlen) -= cando;
2015     bytes -= cando; if (!bytes) break;
2016
2017     /* we only get here if we emptied the output buffer */
2018
2019     /* read data header + data */
2020     inlen = outlen = 0;
2021     while (outlen == 0) {
2022       /* read the block header, skip the reserved part */
2023       if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
2024         return DECR_INPUT;
2025
2026       if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
2027         return DECR_INPUT;
2028
2029       /* we shouldn't get blocks over CAB_INPUTMAX in size */
2030       data = CAB(inbuf) + inlen;
2031       len = EndGetI16(buf+cfdata_CompressedSize);
2032       inlen += len;
2033       if (inlen > CAB_INPUTMAX) return DECR_INPUT;
2034       if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
2035         return DECR_INPUT;
2036
2037       /* clear two bytes after read-in data */
2038       data[len+1] = data[len+2] = 0;
2039
2040       /* perform checksum test on the block (if one is stored) */
2041       cksum = EndGetI32(buf+cfdata_CheckSum);
2042       if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
2043         return DECR_CHECKSUM; /* checksum is wrong */
2044
2045       outlen = EndGetI16(buf+cfdata_UncompressedSize);
2046
2047       /* outlen=0 means this block was the last contiguous part
2048          of a split block, continued in the next cabinet */
2049       if (outlen == 0) {
2050         int pathlen, filenamelen, idx, i, cabhf;
2051         char fullpath[MAX_PATH], userpath[256];
2052         FDINOTIFICATION fdin;
2053         FDICABINETINFO fdici;
2054         char emptystring = '\0';
2055         cab_UBYTE buf2[64];
2056         int success = FALSE;
2057         struct fdi_folder *fol = NULL, *linkfol = NULL; 
2058         struct fdi_file   *file = NULL, *linkfile = NULL;
2059
2060         tryanothercab:
2061
2062         /* set up the next decomp_state... */
2063         if (!(cab->next)) {
2064           if (!cab->mii.hasnext) return DECR_INPUT;
2065
2066           if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
2067             return DECR_NOMEMORY;
2068         
2069           ZeroMemory(cab->next, sizeof(fdi_decomp_state));
2070
2071           /* copy pszCabPath to userpath */
2072           ZeroMemory(userpath, 256);
2073           pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2074           if (pathlen) {
2075             if (pathlen < 256) {
2076               for (i = 0; i <= pathlen; i++)
2077                 userpath[i] = pszCabPath[i];
2078             } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2079           } 
2080
2081           /* initial fdintNEXT_CABINET notification */
2082           ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2083           fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
2084           fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
2085           fdin.psz3 = &userpath[0];
2086           fdin.fdie = FDIERROR_NONE;
2087           fdin.pv = pvUser;
2088
2089           if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2090
2091           do {
2092
2093             pathlen = strlen(userpath);
2094             filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
2095
2096             /* slight overestimation here to save CPU cycles in the developer's brain */
2097             if ((pathlen + filenamelen + 3) > MAX_PATH) {
2098               ERR("MAX_PATH exceeded.\n");
2099               return DECR_ILLEGALDATA;
2100             }
2101
2102             /* paste the path and filename together */
2103             idx = 0;
2104             if (pathlen) {
2105               for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
2106               if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2107             }
2108             if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
2109             fullpath[idx] = '\0';
2110         
2111             TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2112         
2113             /* try to get a handle to the cabfile */
2114             cabhf = PFDI_OPEN(CAB(hfdi), fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2115             if (cabhf == -1) {
2116               /* no file.  allow the user to try again */
2117               fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2118               if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2119               continue;
2120             }
2121         
2122             if (cabhf == 0) {
2123               ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2124               fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2125               if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2126               continue;
2127             }
2128  
2129             /* check if it's really a cabfile. Note that this doesn't implement the bug */
2130             if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
2131               WARN("FDIIsCabinet failed.\n");
2132               PFDI_CLOSE(CAB(hfdi), cabhf);
2133               fdin.fdie = FDIERROR_NOT_A_CABINET;
2134               if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2135               continue;
2136             }
2137
2138             if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
2139               WARN("Wrong Cabinet.\n");
2140               PFDI_CLOSE(CAB(hfdi), cabhf);
2141               fdin.fdie = FDIERROR_WRONG_CABINET;
2142               if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2143               continue;
2144             }
2145            
2146             break;
2147
2148           } while (1);
2149           
2150           /* cabinet notification */
2151           ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2152           fdin.setID = fdici.setID;
2153           fdin.iCabinet = fdici.iCabinet;
2154           fdin.pv = pvUser;
2155           fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2156           fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2157           fdin.psz3 = pszCabPath;
2158         
2159           if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2160           
2161           cab->next->setID = fdici.setID;
2162           cab->next->iCabinet = fdici.iCabinet;
2163           cab->next->hfdi = CAB(hfdi);
2164           cab->next->filehf = CAB(filehf);
2165           cab->next->cabhf = cabhf;
2166           cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2167
2168           cab = cab->next; /* advance to the next cabinet */
2169
2170           /* read folders */
2171           for (i = 0; i < fdici.cFolders; i++) {
2172             if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF) 
2173               return DECR_INPUT;
2174
2175             if (cab->mii.folder_resv > 0)
2176               PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2177         
2178             fol = (struct fdi_folder *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2179             if (!fol) {
2180               ERR("out of memory!\n");
2181               return DECR_NOMEMORY;
2182             }
2183             ZeroMemory(fol, sizeof(struct fdi_folder));
2184             if (!(cab->firstfol)) cab->firstfol = fol;
2185         
2186             fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2187             fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2188             fol->comp_type  = EndGetI16(buf2+cffold_CompType);
2189         
2190             if (linkfol)
2191               linkfol->next = fol; 
2192             linkfol = fol;
2193           }
2194         
2195           /* read files */
2196           for (i = 0; i < fdici.cFiles; i++) {
2197             if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2198               return DECR_INPUT;
2199               
2200             file = (struct fdi_file *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2201             if (!file) {
2202               ERR("out of memory!\n"); 
2203               return DECR_NOMEMORY;
2204             }
2205             ZeroMemory(file, sizeof(struct fdi_file));
2206             if (!(cab->firstfile)) cab->firstfile = file;
2207               
2208             file->length   = EndGetI32(buf2+cffile_UncompressedSize);
2209             file->offset   = EndGetI32(buf2+cffile_FolderOffset);
2210             file->index    = EndGetI16(buf2+cffile_FolderIndex);
2211             file->time     = EndGetI16(buf2+cffile_Time);
2212             file->date     = EndGetI16(buf2+cffile_Date);
2213             file->attribs  = EndGetI16(buf2+cffile_Attribs);
2214             file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2215         
2216             if (!file->filename) return DECR_INPUT;
2217         
2218             if (linkfile)
2219               linkfile->next = file;
2220             linkfile = file;
2221           }
2222         
2223         } else 
2224             cab = cab->next; /* advance to the next cabinet */
2225
2226         /* iterate files -- if we encounter the continued file, process it --
2227            otherwise, jump to the label above and keep looking */
2228
2229         for (file = cab->firstfile; (file); file = file->next) {
2230           if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2231             /* check to ensure a real match */
2232             if (strcasecmp(fi->filename, file->filename) == 0) {
2233               success = TRUE;
2234               if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2235                 return DECR_INPUT;
2236               break;
2237             }
2238           }
2239         }
2240         if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2241                                              "Wrong Cabinet" notification? */
2242       }
2243     }
2244
2245     /* decompress block */
2246     if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2247       return err;
2248     CAB(outlen) = outlen;
2249     CAB(outpos) = CAB(outbuf);
2250   }
2251   
2252   CAB(decomp_cab) = cab;
2253   return DECR_OK;
2254 }
2255
2256 /***********************************************************************
2257  *              FDICopy (CABINET.22)
2258  *
2259  * Iterates through the files in the Cabinet file indicated by name and
2260  * file-location.  May chain forward to additional cabinets (typically
2261  * only one) if files which begin in this Cabinet are continued in another
2262  * cabinet.  For each file which is partially contained in this cabinet,
2263  * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2264  * notification to the pfnfdin callback.  For each file which begins in
2265  * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2266  * callback, and the file is optionally decompressed and saved to disk.
2267  * Notification is not provided for files which are not at least partially
2268  * contained in the specified cabinet file.
2269  *
2270  * See below for a thorough explanation of the various notification
2271  * callbacks.
2272  *
2273  * PARAMS
2274  *   hfdi       [I] An HFDI from FDICreate
2275  *   pszCabinet [I] C-style string containing the filename of the cabinet
2276  *   pszCabPath [I] C-style string containing the file path of the cabinet
2277  *   flags      [I] "Decoder parameters".  Ignored.  Suggested value: 0.
2278  *   pfnfdin    [I] Pointer to a notification function.  See CALLBACKS below.
2279  *   pfnfdid    [I] Pointer to a decryption function.  Ignored.  Suggested
2280  *                  value: NULL.
2281  *   pvUser     [I] arbitrary void * value which is passed to callbacks.
2282  *
2283  * RETURNS
2284  *   TRUE if successful.
2285  *   FALSE if unsuccessful (error information is provided in the ERF structure
2286  *     associated with the provided decompression handle by FDICreate).
2287  *
2288  * CALLBACKS
2289  *
2290  *   Two pointers to callback functions are provided as parameters to FDICopy:
2291  *   pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT).  These
2292  *   types are as follows:
2293  *
2294  *     typedef INT_PTR (__cdecl *PFNFDINOTIFY)  ( FDINOTIFICATIONTYPE fdint,
2295  *                                               PFDINOTIFICATION  pfdin );
2296  *
2297  *     typedef int     (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2298  *
2299  *   You can create functions of this type using the FNFDINOTIFY() and
2300  *   FNFDIDECRYPT() macros, respectively.  For example:
2301  *
2302  *     FNFDINOTIFY(mycallback) {
2303  *       / * use variables fdint and pfdin to process notification * /
2304  *     }
2305  *
2306  *   The second callback, which could be used for decrypting encrypted data,
2307  *   is not used at all.
2308  *
2309  *   Each notification informs the user of some event which has occurred during
2310  *   decompression of the cabinet file; each notification is also an opportunity
2311  *   for the callee to abort decompression.  The information provided to the
2312  *   callback and the meaning of the callback's return value vary drastically
2313  *   across the various types of notification.  The type of notification is the
2314  *   fdint parameter; all other information is provided to the callback in
2315  *   notification-specific parts of the FDINOTIFICATION structure pointed to by
2316  *   pfdin.  The only part of that structure which is assigned for every callback
2317  *   is the pv element, which contains the arbitrary value which was passed to
2318  *   FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2319  *   is highly dependent on fdint).
2320  *   
2321  *   If you encounter unknown notifications, you should return zero if you want
2322  *   decompression to continue (or -1 to abort).  All strings used in the
2323  *   callbacks are regular C-style strings.  Detailed descriptions of each
2324  *   notification type follow:
2325  *
2326  *   fdintCABINET_INFO:
2327  * 
2328  *     This is the first notification provided after calling FDICopy, and provides
2329  *     the user with various information about the cabinet.  Note that this is
2330  *     called for each cabinet FDICopy opens, not just the first one.  In the
2331  *     structure pointed to by pfdin, psz1 contains a pointer to the name of the
2332  *     next cabinet file in the set after the one just loaded (if any), psz2
2333  *     contains a pointer to the name or "info" of the next disk, psz3
2334  *     contains a pointer to the file-path of the current cabinet, setID
2335  *     contains an arbitrary constant associated with this set of cabinet files,
2336  *     and iCabinet contains the numerical index of the current cabinet within
2337  *     that set.  Return zero, or -1 to abort.
2338  *
2339  *   fdintPARTIAL_FILE:
2340  *
2341  *     This notification is provided when FDICopy encounters a part of a file
2342  *     contained in this cabinet which is missing its beginning.  Files can be
2343  *     split across cabinets, so this is not necessarily an abnormality; it just
2344  *     means that the file in question begins in another cabinet.  No file
2345  *     corresponding to this notification is extracted from the cabinet.  In the
2346  *     structure pointed to by pfdin, psz1 contains a pointer to the name of the
2347  *     partial file, psz2 contains a pointer to the file name of the cabinet in
2348  *     which this file begins, and psz3 contains a pointer to the disk name or
2349  *     "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2350  *
2351  *   fdintCOPY_FILE:
2352  *
2353  *     This notification is provided when FDICopy encounters a file which starts
2354  *     in the cabinet file, provided to FDICopy in pszCabinet.  (FDICopy will not
2355  *     look for files in cabinets after the first one).  One notification will be
2356  *     sent for each such file, before the file is decompressed.  By returning
2357  *     zero, the callback can instruct FDICopy to skip the file.  In the structure
2358  *     pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2359  *     the size of the file (uncompressed), attribs contains the file attributes,
2360  *     and date and time contain the date and time of the file.  attributes, date,
2361  *     and time are of the 16-bit ms-dos variety.  Return -1 to abort decompression
2362  *     for the entire cabinet, 0 to skip just this file but continue scanning the
2363  *     cabinet for more files, or an FDIClose()-compatible file-handle.
2364  *
2365  *   fdintCLOSE_FILE_INFO:
2366  *
2367  *     This notification is important, don't forget to implement it.  This
2368  *     notification indicates that a file has been successfully uncompressed and
2369  *     written to disk.  Upon receipt of this notification, the callee is expected
2370  *     to close the file handle, to set the attributes and date/time of the
2371  *     closed file, and possibly to execute the file.  In the structure pointed to
2372  *     by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2373  *     open file handle (close it), cb contains 1 or zero, indicating respectively
2374  *     that the callee should or should not execute the file, and date, time
2375  *     and attributes will be set as in fdintCOPY_FILE.  Bizarrely, the Cabinet SDK
2376  *     specifies that _A_EXEC will be xor'ed out of attributes!  wine does not do
2377  *     do so.  Return TRUE, or FALSE to abort decompression.
2378  *
2379  *   fdintNEXT_CABINET:
2380  *
2381  *     This notification is called when FDICopy must load in another cabinet.  This
2382  *     can occur when a file's data is "split" across multiple cabinets.  The
2383  *     callee has the opportunity to request that FDICopy look in a different file
2384  *     path for the specified cabinet file, by writing that data into a provided
2385  *     buffer (see below for more information).  This notification will be received
2386  *     more than once per-cabinet in the instance that FDICopy failed to find a
2387  *     valid cabinet at the location specified by the first per-cabinet
2388  *     fdintNEXT_CABINET notification.  In such instances, the fdie element of the
2389  *     structure pointed to by pfdin indicates the error which prevented FDICopy
2390  *     from proceeding successfully.  Return zero to indicate success, or -1 to
2391  *     indicate failure and abort FDICopy.
2392  *
2393  *     Upon receipt of this notification, the structure pointed to by pfdin will
2394  *     contain the following values: psz1 pointing to the name of the cabinet
2395  *     which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2396  *     the next disk, psz3 pointing to the presumed file-location of the cabinet,
2397  *     and fdie containing either FDIERROR_NONE, or one of the following: 
2398  *
2399  *       FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2400  *       FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2401  *       FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and 
2402  *       FDIERROR_WRONG_CABINET.
2403  *
2404  *     The callee may choose to change the path where FDICopy will look for the
2405  *     cabinet after this notification.  To do so, the caller may write the new
2406  *     pathname to the buffer pointed to by psz3, which is 256 characters in
2407  *     length, including the terminating null character, before returning zero.
2408  *
2409  *   fdintENUMERATE:
2410  *
2411  *     Undocumented and unimplemented in wine, this seems to be sent each time
2412  *     a cabinet is opened, along with the fdintCABINET_INFO notification.  It
2413  *     probably has an interface similar to that of fdintCABINET_INFO; maybe this
2414  *     provides information about the current cabinet instead of the next one....
2415  *     this is just a guess, it has not been looked at closely.
2416  *
2417  * INCLUDES
2418  *   fdi.c
2419  */
2420 BOOL __cdecl FDICopy(
2421         HFDI           hfdi,
2422         char          *pszCabinet,
2423         char          *pszCabPath,
2424         int            flags,
2425         PFNFDINOTIFY   pfnfdin,
2426         PFNFDIDECRYPT  pfnfdid,
2427         void          *pvUser)
2428
2429   FDICABINETINFO    fdici;
2430   FDINOTIFICATION   fdin;
2431   int               cabhf, filehf = 0, idx;
2432   unsigned int      i;
2433   char              fullpath[MAX_PATH];
2434   size_t            pathlen, filenamelen;
2435   char              emptystring = '\0';
2436   cab_UBYTE         buf[64];
2437   struct fdi_folder *fol = NULL, *linkfol = NULL; 
2438   struct fdi_file   *file = NULL, *linkfile = NULL;
2439   fdi_decomp_state _decomp_state;
2440   fdi_decomp_state *decomp_state = &_decomp_state;
2441
2442   TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, "
2443         "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2444         hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2445
2446   if (!REALLY_IS_FDI(hfdi)) {
2447     SetLastError(ERROR_INVALID_HANDLE);
2448     return FALSE;
2449   }
2450
2451   ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2452
2453   pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2454   filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2455
2456   /* slight overestimation here to save CPU cycles in the developer's brain */
2457   if ((pathlen + filenamelen + 3) > MAX_PATH) {
2458     ERR("MAX_PATH exceeded.\n");
2459     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2460     PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2461     PFDI_INT(hfdi)->perf->fError = TRUE;
2462     SetLastError(ERROR_FILE_NOT_FOUND);
2463     return FALSE;
2464   }
2465
2466   /* paste the path and filename together */
2467   idx = 0;
2468   if (pathlen) {
2469     for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2470     if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2471   }
2472   if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2473   fullpath[idx] = '\0';
2474
2475   TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2476
2477   /* get a handle to the cabfile */
2478   cabhf = PFDI_OPEN(hfdi, fullpath, _O_RDONLY|_O_BINARY, _S_IREAD | _S_IWRITE);
2479   if (cabhf == -1) {
2480     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2481     PFDI_INT(hfdi)->perf->fError = TRUE;
2482     SetLastError(ERROR_FILE_NOT_FOUND);
2483     return FALSE;
2484   }
2485
2486   if (cabhf == 0) {
2487     ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2488     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2489     PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2490     PFDI_INT(hfdi)->perf->fError = TRUE;
2491     SetLastError(ERROR_FILE_NOT_FOUND);
2492     return FALSE;
2493   }
2494
2495   /* check if it's really a cabfile. Note that this doesn't implement the bug */
2496   if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2497     ERR("FDIIsCabinet failed.\n");
2498     PFDI_CLOSE(hfdi, cabhf);
2499     return FALSE;
2500   }
2501    
2502   /* cabinet notification */
2503   ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2504   fdin.setID = fdici.setID;
2505   fdin.iCabinet = fdici.iCabinet;
2506   fdin.pv = pvUser;
2507   fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2508   fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2509   fdin.psz3 = pszCabPath;
2510
2511   if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2512     PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2513     PFDI_INT(hfdi)->perf->erfType = 0;
2514     PFDI_INT(hfdi)->perf->fError = TRUE;
2515     goto bail_and_fail;
2516   }
2517
2518   CAB(setID) = fdici.setID;
2519   CAB(iCabinet) = fdici.iCabinet;
2520   CAB(cabhf) = cabhf;
2521
2522   /* read folders */
2523   for (i = 0; i < fdici.cFolders; i++) {
2524     if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2525       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2526       PFDI_INT(hfdi)->perf->erfType = 0;
2527       PFDI_INT(hfdi)->perf->fError = TRUE;
2528       goto bail_and_fail;
2529     }
2530
2531     if (CAB(mii).folder_resv > 0)
2532       PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2533
2534     fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2535     if (!fol) {
2536       ERR("out of memory!\n");
2537       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2538       PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2539       PFDI_INT(hfdi)->perf->fError = TRUE;
2540       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2541       goto bail_and_fail;
2542     }
2543     ZeroMemory(fol, sizeof(struct fdi_folder));
2544     if (!CAB(firstfol)) CAB(firstfol) = fol;
2545
2546     fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2547     fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2548     fol->comp_type  = EndGetI16(buf+cffold_CompType);
2549
2550     if (linkfol)
2551       linkfol->next = fol; 
2552     linkfol = fol;
2553   }
2554
2555   /* read files */
2556   for (i = 0; i < fdici.cFiles; i++) {
2557     if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2558       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2559       PFDI_INT(hfdi)->perf->erfType = 0;
2560       PFDI_INT(hfdi)->perf->fError = TRUE;
2561       goto bail_and_fail;
2562     }
2563
2564     file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2565     if (!file) { 
2566       ERR("out of memory!\n"); 
2567       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2568       PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2569       PFDI_INT(hfdi)->perf->fError = TRUE;
2570       SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2571       goto bail_and_fail;
2572     }
2573     ZeroMemory(file, sizeof(struct fdi_file));
2574     if (!CAB(firstfile)) CAB(firstfile) = file;
2575       
2576     file->length   = EndGetI32(buf+cffile_UncompressedSize);
2577     file->offset   = EndGetI32(buf+cffile_FolderOffset);
2578     file->index    = EndGetI16(buf+cffile_FolderIndex);
2579     file->time     = EndGetI16(buf+cffile_Time);
2580     file->date     = EndGetI16(buf+cffile_Date);
2581     file->attribs  = EndGetI16(buf+cffile_Attribs);
2582     file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2583
2584     if (!file->filename) {
2585       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2586       PFDI_INT(hfdi)->perf->erfType = 0;
2587       PFDI_INT(hfdi)->perf->fError = TRUE;
2588       goto bail_and_fail;
2589     }
2590
2591     if (linkfile)
2592       linkfile->next = file;
2593     linkfile = file;
2594   }
2595
2596   for (file = CAB(firstfile); (file); file = file->next) {
2597
2598     /*
2599      * FIXME: This implementation keeps multiple cabinet files open at once
2600      * when encountering a split cabinet.  It is a quirk of this implementation
2601      * that sometimes we decrypt the same block of data more than once, to find
2602      * the right starting point for a file, moving the file-pointer backwards.
2603      * If we kept a cache of certain file-pointer information, we could eliminate
2604      * that behavior... in fact I am not sure that the caching we already have
2605      * is not sufficient.
2606      * 
2607      * The current implementation seems to work fine in straightforward situations
2608      * where all the cabinet files needed for decryption are simultaneously
2609      * available.  But presumably, the API is supposed to support cabinets which
2610      * are split across multiple CDROMS; we may need to change our implementation
2611      * to strictly serialize it's file usage so that it opens only one cabinet
2612      * at a time.  Some experimentation with Windows is needed to figure out the
2613      * precise semantics required.  The relevant code is here and in fdi_decomp().
2614      */
2615
2616     /* partial-file notification */
2617     if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2618       /*
2619        * FIXME: Need to create a Cabinet with a single file spanning multiple files
2620        * and perform some tests to figure out the right behavior.  The SDK says
2621        * FDICopy will notify the user of the filename and "disk name" (info) of
2622        * the cabinet where the spanning file /started/.
2623        *
2624        * That would certainly be convenient for the API-user, who could abort,
2625        * everything (or parallelize, if that's allowed (it is in wine)), and call
2626        * FDICopy again with the provided filename, so as to avoid partial file
2627        * notification and successfully unpack.  This task could be quite unpleasant
2628        * from wine's perspective: the information specifying the "start cabinet" for
2629        * a file is associated nowhere with the file header and is not to be found in
2630        * the cabinet header.  We have only the index of the cabinet wherein the folder
2631        * begins, which contains the file.  To find that cabinet, we must consider the
2632        * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2633        * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2634        * list).
2635        *
2636        * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2637        * cabinet other than the active one might be at another filepath than the
2638        * current one, or on another CDROM. This could get rather dicey, especially
2639        * if we imagine parallelized access to the FDICopy API.
2640        *
2641        * The current implementation punts -- it just returns the previous cabinet and
2642        * it's info from the header of this cabinet.  This provides the right answer in
2643        * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2644        * we "fix" it.
2645        */
2646       ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2647       fdin.pv = pvUser;
2648       fdin.psz1 = (char *)file->filename;
2649       fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2650       fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2651
2652       if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2653         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2654         PFDI_INT(hfdi)->perf->erfType = 0;
2655         PFDI_INT(hfdi)->perf->fError = TRUE;
2656         goto bail_and_fail;
2657       }
2658       /* I don't think we are supposed to decompress partial files.  This prevents it. */
2659       file->oppressed = TRUE;
2660     }
2661     if (file->oppressed) {
2662       filehf = 0;
2663     } else {
2664       ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2665       fdin.pv = pvUser;
2666       fdin.psz1 = (char *)file->filename;
2667       fdin.cb = file->length;
2668       fdin.date = file->date;
2669       fdin.time = file->time;
2670       fdin.attribs = file->attribs;
2671       if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2672         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2673         PFDI_INT(hfdi)->perf->erfType = 0;
2674         PFDI_INT(hfdi)->perf->fError = TRUE;
2675         filehf = 0;
2676         goto bail_and_fail;
2677       }
2678     }
2679
2680     /* find the folder for this file if necc. */
2681     if (filehf) {
2682       int i2;
2683
2684       fol = CAB(firstfol);
2685       if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2686         /* pick the last folder */
2687         while (fol->next) fol = fol->next;
2688       } else {
2689         for (i2 = 0; (i2 < file->index); i2++)
2690           if (fol->next) /* bug resistance, should always be true */
2691             fol = fol->next;
2692       }
2693     }
2694
2695     if (filehf) {
2696       cab_UWORD comptype = fol->comp_type;
2697       int ct1 = comptype & cffoldCOMPTYPE_MASK;
2698       int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2699       int err = 0;
2700
2701       TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2702
2703       /* set up decomp_state */
2704       CAB(hfdi) = hfdi;
2705       CAB(filehf) = filehf;
2706
2707       /* Was there a change of folder?  Compression type?  Did we somehow go backwards? */
2708       if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2709
2710         TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2711
2712         /* free stuff for the old decompresser */
2713         switch (ct2) {
2714         case cffoldCOMPTYPE_LZX:
2715           if (LZX(window)) {
2716             PFDI_FREE(hfdi, LZX(window));
2717             LZX(window) = NULL;
2718           }
2719           break;
2720         case cffoldCOMPTYPE_QUANTUM:
2721           if (QTM(window)) {
2722             PFDI_FREE(hfdi, QTM(window));
2723             QTM(window) = NULL;
2724           }
2725           break;
2726         }
2727
2728         CAB(decomp_cab) = NULL;
2729         PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2730         CAB(offset) = 0;
2731         CAB(outlen) = 0;
2732
2733         /* initialize the new decompresser */
2734         switch (ct1) {
2735         case cffoldCOMPTYPE_NONE:
2736           CAB(decompress) = NONEfdi_decomp;
2737           break;
2738         case cffoldCOMPTYPE_MSZIP:
2739           CAB(decompress) = ZIPfdi_decomp;
2740           break;
2741         case cffoldCOMPTYPE_QUANTUM:
2742           CAB(decompress) = QTMfdi_decomp;
2743           err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2744           break;
2745         case cffoldCOMPTYPE_LZX:
2746           CAB(decompress) = LZXfdi_decomp;
2747           err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2748           break;
2749         default:
2750           err = DECR_DATAFORMAT;
2751         }
2752       }
2753
2754       CAB(current) = fol;
2755
2756       switch (err) {
2757         case DECR_OK:
2758           break;
2759         case DECR_NOMEMORY:
2760           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2761           PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2762           PFDI_INT(hfdi)->perf->fError = TRUE;
2763           SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2764           goto bail_and_fail;
2765         default:
2766           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2767           PFDI_INT(hfdi)->perf->erfOper = 0;
2768           PFDI_INT(hfdi)->perf->fError = TRUE;
2769           goto bail_and_fail;
2770       }
2771
2772       if (file->offset > CAB(offset)) {
2773         /* decode bytes and send them to /dev/null */
2774         switch ((err = fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser))) {
2775           case DECR_OK:
2776             break;
2777           case DECR_USERABORT:
2778             PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2779             PFDI_INT(hfdi)->perf->erfType = 0;
2780             PFDI_INT(hfdi)->perf->fError = TRUE;
2781             goto bail_and_fail;
2782           case DECR_NOMEMORY:
2783             PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2784             PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2785             PFDI_INT(hfdi)->perf->fError = TRUE;
2786             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2787             goto bail_and_fail;
2788           default:
2789             PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2790             PFDI_INT(hfdi)->perf->erfOper = 0;
2791             PFDI_INT(hfdi)->perf->fError = TRUE;
2792             goto bail_and_fail;
2793         }
2794         CAB(offset) = file->offset;
2795       }
2796
2797       /* now do the actual decompression */
2798       err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2799       if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2800
2801       /* fdintCLOSE_FILE_INFO notification */
2802       ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2803       fdin.pv = pvUser;
2804       fdin.psz1 = (char *)file->filename;
2805       fdin.hf = filehf;
2806       fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2807       fdin.date = file->date;
2808       fdin.time = file->time;
2809       fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2810       ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2811       filehf = 0;
2812
2813       switch (err) {
2814         case DECR_OK:
2815           break;
2816         case DECR_USERABORT:
2817           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2818           PFDI_INT(hfdi)->perf->erfType = 0;
2819           PFDI_INT(hfdi)->perf->fError = TRUE;
2820           goto bail_and_fail;
2821         case DECR_NOMEMORY:
2822           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2823           PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2824           PFDI_INT(hfdi)->perf->fError = TRUE;
2825           SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2826           goto bail_and_fail;
2827         default:
2828           PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2829           PFDI_INT(hfdi)->perf->erfOper = 0;
2830           PFDI_INT(hfdi)->perf->fError = TRUE;
2831           goto bail_and_fail;
2832       }
2833     }
2834   }
2835
2836   /* free decompression temps */
2837   switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2838   case cffoldCOMPTYPE_LZX:
2839     if (LZX(window)) {
2840       PFDI_FREE(hfdi, LZX(window));
2841       LZX(window) = NULL;
2842     }
2843     break;
2844   case cffoldCOMPTYPE_QUANTUM:
2845     if (QTM(window)) {
2846       PFDI_FREE(hfdi, QTM(window));
2847       QTM(window) = NULL;
2848     }
2849     break;
2850   }
2851
2852   while (decomp_state) {
2853     fdi_decomp_state *prev_fds;
2854
2855     PFDI_CLOSE(hfdi, CAB(cabhf));
2856
2857     /* free the storage remembered by mii */
2858     if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2859     if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2860     if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2861     if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2862
2863     while (CAB(firstfol)) {
2864       fol = CAB(firstfol);
2865       CAB(firstfol) = CAB(firstfol)->next;
2866       PFDI_FREE(hfdi, fol);
2867     }
2868     while (CAB(firstfile)) {
2869       file = CAB(firstfile);
2870       if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2871       CAB(firstfile) = CAB(firstfile)->next;
2872       PFDI_FREE(hfdi, file);
2873     }
2874     prev_fds = decomp_state;
2875     decomp_state = CAB(next);
2876     if (prev_fds != &_decomp_state)
2877       PFDI_FREE(hfdi, prev_fds);
2878   }
2879  
2880   return TRUE;
2881
2882   bail_and_fail: /* here we free ram before error returns */
2883
2884   /* free decompression temps */
2885   switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2886   case cffoldCOMPTYPE_LZX:
2887     if (LZX(window)) {
2888       PFDI_FREE(hfdi, LZX(window));
2889       LZX(window) = NULL;
2890     }
2891     break;
2892   case cffoldCOMPTYPE_QUANTUM:
2893     if (QTM(window)) {
2894       PFDI_FREE(hfdi, QTM(window));
2895       QTM(window) = NULL;
2896     }
2897     break;
2898   }
2899
2900   if (filehf) PFDI_CLOSE(hfdi, filehf);
2901
2902   while (decomp_state) {
2903     fdi_decomp_state *prev_fds;
2904
2905     PFDI_CLOSE(hfdi, CAB(cabhf));
2906
2907     /* free the storage remembered by mii */
2908     if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2909     if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2910     if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2911     if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2912
2913     while (CAB(firstfol)) {
2914       fol = CAB(firstfol);
2915       CAB(firstfol) = CAB(firstfol)->next;
2916       PFDI_FREE(hfdi, fol);
2917     }
2918     while (CAB(firstfile)) {
2919       file = CAB(firstfile);
2920       if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2921       CAB(firstfile) = CAB(firstfile)->next;
2922       PFDI_FREE(hfdi, file);
2923     }
2924     prev_fds = decomp_state;
2925     decomp_state = CAB(next);
2926     if (prev_fds != &_decomp_state)
2927       PFDI_FREE(hfdi, prev_fds);
2928   }
2929
2930   return FALSE;
2931 }
2932
2933 /***********************************************************************
2934  *              FDIDestroy (CABINET.23)
2935  *
2936  * Frees a handle created by FDICreate.  Do /not/ call this in the middle
2937  * of FDICopy.  Only reason for failure would be an invalid handle.
2938  * 
2939  * PARAMS
2940  *   hfdi [I] The HFDI to free
2941  *
2942  * RETURNS
2943  *   TRUE for success
2944  *   FALSE for failure
2945  */
2946 BOOL __cdecl FDIDestroy(HFDI hfdi)
2947 {
2948   TRACE("(hfdi == ^%p)\n", hfdi);
2949   if (REALLY_IS_FDI(hfdi)) {
2950     PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2951     PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2952     return TRUE;
2953   } else {
2954     SetLastError(ERROR_INVALID_HANDLE);
2955     return FALSE;
2956   }
2957 }
2958
2959 /***********************************************************************
2960  *              FDITruncateCabinet (CABINET.24)
2961  *
2962  * Removes all folders of a cabinet file after and including the
2963  * specified folder number.
2964  * 
2965  * PARAMS
2966  *   hfdi            [I] Handle to the FDI context.
2967  *   pszCabinetName  [I] Filename of the cabinet.
2968  *   iFolderToDelete [I] Index of the first folder to delete.
2969  * 
2970  * RETURNS
2971  *   Success: TRUE.
2972  *   Failure: FALSE.
2973  * 
2974  * NOTES
2975  *   The PFNWRITE function supplied to FDICreate must truncate the
2976  *   file at the current position if the number of bytes to write is 0.
2977  */
2978 BOOL __cdecl FDITruncateCabinet(
2979         HFDI    hfdi,
2980         char   *pszCabinetName,
2981         USHORT  iFolderToDelete)
2982 {
2983   FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2984     hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
2985
2986   if (!REALLY_IS_FDI(hfdi)) {
2987     SetLastError(ERROR_INVALID_HANDLE);
2988     return FALSE;
2989   }
2990
2991   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2992   return FALSE;
2993 }