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