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