~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/cabinet/fdi.c

Version: ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * File Decompression Interface
  3  *
  4  * Copyright 2000-2002 Stuart Caie
  5  * Copyright 2002 Patrik Stridvall
  6  * Copyright 2003 Greg Turner
  7  *
  8  * This library is free software; you can redistribute it and/or
  9  * modify it under the terms of the GNU Lesser General Public
 10  * License as published by the Free Software Foundation; either
 11  * version 2.1 of the License, or (at your option) any later version.
 12  *
 13  * This library is distributed in the hope that it will be useful,
 14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16  * Lesser General Public License for more details.
 17  *
 18  * You should have received a copy of the GNU Lesser General Public
 19  * License along with this library; if not, write to the Free Software
 20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 21  *
 22  *
 23  * This is a largely redundant reimplementation of the stuff in cabextract.c.  It
 24  * would be theoretically preferable to have only one, shared implementation, however
 25  * there are semantic differences which may discourage efforts to unify the two.  It
 26  * should be possible, if awkward, to go back and reimplement cabextract.c using FDI.
 27  * But this approach would be quite a bit less performant.  Probably a better way
 28  * would be to create a "library" of routines in cabextract.c which do the actual
 29  * decompression, and have both fdi.c and cabextract share those routines.  The rest
 30  * of the code is not sufficiently similar to merit a shared implementation.
 31  *
 32  * The worst thing about this API is the bug.  "The bug" is this: when you extract a
 33  * cabinet, it /always/ informs you (via the hasnext field of PFDICABINETINFO), that
 34  * there is no subsequent cabinet, even if there is one.  wine faithfully reproduces
 35  * this behavior.
 36  *
 37  * TODO:
 38  *
 39  * Wine does not implement the AFAIK undocumented "enumerate" callback during
 40  * FDICopy.  It is implemented in Windows and therefore worth investigating...
 41  *
 42  * Lots of pointers flying around here... am I leaking RAM?
 43  *
 44  * WTF is FDITruncate?
 45  *
 46  * Probably, I need to weed out some dead code-paths.
 47  *
 48  * Test unit(s).
 49  *
 50  * The fdintNEXT_CABINET callbacks are probably not working quite as they should.
 51  * There are several FIXME's in the source describing some of the deficiencies in
 52  * some detail.  Additionally, we do not do a very good job of returning the right
 53  * error codes to this callback.
 54  *
 55  * FDICopy and fdi_decomp are incomprehensibly large; separating these into smaller
 56  * functions would be nice.
 57  *
 58  *   -gmt
 59  */
 60 
 61 #include "config.h"
 62 
 63 #include <stdarg.h>
 64 #include <stdio.h>
 65 
 66 #include "windef.h"
 67 #include "winbase.h"
 68 #include "winerror.h"
 69 #include "fdi.h"
 70 #include "cabinet.h"
 71 
 72 #include "wine/debug.h"
 73 
 74 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
 75 
 76 THOSE_ZIP_CONSTS;
 77 
 78 struct fdi_file {
 79   struct fdi_file *next;               /* next file in sequence          */
 80   LPCSTR filename;                     /* output name of file            */
 81   int    fh;                           /* open file handle or NULL       */
 82   cab_ULONG length;                    /* uncompressed length of file    */
 83   cab_ULONG offset;                    /* uncompressed offset in folder  */
 84   cab_UWORD index;                     /* magic index number of folder   */
 85   cab_UWORD time, date, attribs;       /* MS-DOS time/date/attributes    */
 86   BOOL oppressed;                      /* never to be processed          */
 87 };
 88 
 89 struct fdi_folder {
 90   struct fdi_folder *next;
 91   cab_off_t offset;                    /* offset to data blocks (32 bit) */
 92   cab_UWORD comp_type;                 /* compression format/window size */
 93   cab_ULONG comp_size;                 /* compressed size of folder      */
 94   cab_UBYTE num_splits;                /* number of split blocks + 1     */
 95   cab_UWORD num_blocks;                /* total number of blocks         */
 96 };
 97 
 98 /*
 99  * this structure fills the gaps between what is available in a PFDICABINETINFO
100  * vs what is needed by FDICopy.  Memory allocated for these becomes the responsibility
101  * of the caller to free.  Yes, I am aware that this is totally, utterly inelegant.
102  * To make things even more unnecessarily confusing, we now attach these to the
103  * fdi_decomp_state.
104  */
105 typedef struct {
106    char *prevname, *previnfo;
107    char *nextname, *nextinfo;
108    BOOL hasnext;  /* bug free indicator */
109    int folder_resv, header_resv;
110    cab_UBYTE block_resv;
111 } MORE_ISCAB_INFO, *PMORE_ISCAB_INFO;
112 
113 /*
114  * ugh, well, this ended up being pretty damn silly...
115  * now that I've conceded to build equivalent structures to struct cab.*,
116  * I should have just used those, or, better yet, unified the two... sue me.
117  * (Note to Microsoft: That's a joke.  Please /don't/ actually sue me! -gmt).
118  * Nevertheless, I've come this far, it works, so I'm not gonna change it
119  * for now.  This implementation has significant semantic differences anyhow.
120  */
121 
122 typedef struct fdi_cds_fwd {
123   void *hfdi;                      /* the hfdi we are using                 */
124   INT_PTR filehf, cabhf;           /* file handle we are using              */
125   struct fdi_folder *current;      /* current folder we're extracting from  */
126   cab_ULONG offset;                /* uncompressed offset within folder     */
127   cab_UBYTE *outpos;               /* (high level) start of data to use up  */
128   cab_UWORD outlen;                /* (high level) amount of data to use up */
129   int (*decompress)(int, int, struct fdi_cds_fwd *); /* chosen compress fn  */
130   cab_UBYTE inbuf[CAB_INPUTMAX+2]; /* +2 for lzx bitbuffer overflows!       */
131   cab_UBYTE outbuf[CAB_BLOCKMAX];
132   union {
133     struct ZIPstate zip;
134     struct QTMstate qtm;
135     struct LZXstate lzx;
136   } methods;
137   /* some temp variables for use during decompression */
138   cab_UBYTE q_length_base[27], q_length_extra[27], q_extra_bits[42];
139   cab_ULONG q_position_base[42];
140   cab_ULONG lzx_position_base[51];
141   cab_UBYTE extra_bits[51];
142   USHORT  setID;                   /* Cabinet set ID */
143   USHORT  iCabinet;                /* Cabinet number in set (0 based) */
144   struct fdi_cds_fwd *decomp_cab;
145   MORE_ISCAB_INFO mii;
146   struct fdi_folder *firstfol; 
147   struct fdi_file   *firstfile;
148   struct fdi_cds_fwd *next;
149 } fdi_decomp_state;
150 
151 /****************************************************************
152  * QTMupdatemodel (internal)
153  */
154 void QTMupdatemodel(struct QTMmodel *model, int sym) {
155   struct QTMmodelsym temp;
156   int i, j;
157 
158   for (i = 0; i < sym; i++) model->syms[i].cumfreq += 8;
159 
160   if (model->syms[0].cumfreq > 3800) {
161     if (--model->shiftsleft) {
162       for (i = model->entries - 1; i >= 0; i--) {
163         /* -1, not -2; the 0 entry saves this */
164         model->syms[i].cumfreq >>= 1;
165         if (model->syms[i].cumfreq <= model->syms[i+1].cumfreq) {
166           model->syms[i].cumfreq = model->syms[i+1].cumfreq + 1;
167         }
168       }
169     }
170     else {
171       model->shiftsleft = 50;
172       for (i = 0; i < model->entries ; i++) {
173         /* no -1, want to include the 0 entry */
174         /* this converts cumfreqs into frequencies, then shifts right */
175         model->syms[i].cumfreq -= model->syms[i+1].cumfreq;
176         model->syms[i].cumfreq++; /* avoid losing things entirely */
177         model->syms[i].cumfreq >>= 1;
178       }
179 
180       /* now sort by frequencies, decreasing order -- this must be an
181        * inplace selection sort, or a sort with the same (in)stability
182        * characteristics
183        */
184       for (i = 0; i < model->entries - 1; i++) {
185         for (j = i + 1; j < model->entries; j++) {
186           if (model->syms[i].cumfreq < model->syms[j].cumfreq) {
187             temp = model->syms[i];
188             model->syms[i] = model->syms[j];
189             model->syms[j] = temp;
190           }
191         }
192       }
193 
194       /* then convert frequencies back to cumfreq */
195       for (i = model->entries - 1; i >= 0; i--) {
196         model->syms[i].cumfreq += model->syms[i+1].cumfreq;
197       }
198       /* then update the other part of the table */
199       for (i = 0; i < model->entries; i++) {
200         model->tabloc[model->syms[i].sym] = i;
201       }
202     }
203   }
204 }
205 
206 /*************************************************************************
207  * make_decode_table (internal)
208  *
209  * This function was coded by David Tritscher. It builds a fast huffman
210  * decoding table out of just a canonical huffman code lengths table.
211  *
212  * PARAMS
213  *   nsyms:  total number of symbols in this huffman tree.
214  *   nbits:  any symbols with a code length of nbits or less can be decoded
215  *           in one lookup of the table.
216  *   length: A table to get code lengths from [0 to syms-1]
217  *   table:  The table to fill up with decoded symbols and pointers.
218  *
219  * RETURNS
220  *   OK:    0
221  *   error: 1
222  */
223 int make_decode_table(cab_ULONG nsyms, cab_ULONG nbits, const cab_UBYTE *length, cab_UWORD *table) {
224   register cab_UWORD sym;
225   register cab_ULONG leaf;
226   register cab_UBYTE bit_num = 1;
227   cab_ULONG fill;
228   cab_ULONG pos         = 0; /* the current position in the decode table */
229   cab_ULONG table_mask  = 1 << nbits;
230   cab_ULONG bit_mask    = table_mask >> 1; /* don't do 0 length codes */
231   cab_ULONG next_symbol = bit_mask; /* base of allocation for long codes */
232 
233   /* fill entries for codes short enough for a direct mapping */
234   while (bit_num <= nbits) {
235     for (sym = 0; sym < nsyms; sym++) {
236       if (length[sym] == bit_num) {
237         leaf = pos;
238 
239         if((pos += bit_mask) > table_mask) return 1; /* table overrun */
240 
241         /* fill all possible lookups of this symbol with the symbol itself */
242         fill = bit_mask;
243         while (fill-- > 0) table[leaf++] = sym;
244       }
245     }
246     bit_mask >>= 1;
247     bit_num++;
248   }
249 
250   /* if there are any codes longer than nbits */
251   if (pos != table_mask) {
252     /* clear the remainder of the table */
253     for (sym = pos; sym < table_mask; sym++) table[sym] = 0;
254 
255     /* give ourselves room for codes to grow by up to 16 more bits */
256     pos <<= 16;
257     table_mask <<= 16;
258     bit_mask = 1 << 15;
259 
260     while (bit_num <= 16) {
261       for (sym = 0; sym < nsyms; sym++) {
262         if (length[sym] == bit_num) {
263           leaf = pos >> 16;
264           for (fill = 0; fill < bit_num - nbits; fill++) {
265             /* if this path hasn't been taken yet, 'allocate' two entries */
266             if (table[leaf] == 0) {
267               table[(next_symbol << 1)] = 0;
268               table[(next_symbol << 1) + 1] = 0;
269               table[leaf] = next_symbol++;
270             }
271             /* follow the path and select either left or right for next bit */
272             leaf = table[leaf] << 1;
273             if ((pos >> (15-fill)) & 1) leaf++;
274           }
275           table[leaf] = sym;
276 
277           if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
278         }
279       }
280       bit_mask >>= 1;
281       bit_num++;
282     }
283   }
284 
285   /* full table? */
286   if (pos == table_mask) return 0;
287 
288   /* either erroneous table, or all elements are 0 - let's find out. */
289   for (sym = 0; sym < nsyms; sym++) if (length[sym]) return 1;
290   return 0;
291 }
292 
293 /*************************************************************************
294  * checksum (internal)
295  */
296 cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum) {
297   int len;
298   cab_ULONG ul = 0;
299 
300   for (len = bytes >> 2; len--; data += 4) {
301     csum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
302   }
303 
304   switch (bytes & 3) {
305   case 3: ul |= *data++ << 16;
306   case 2: ul |= *data++ <<  8;
307   case 1: ul |= *data;
308   }
309   csum ^= ul;
310 
311   return csum;
312 }
313 
314 /***********************************************************************
315  *              FDICreate (CABINET.20)
316  *
317  * Provided with several callbacks (all of them are mandatory),
318  * returns a handle which can be used to perform operations
319  * on cabinet files.
320  *
321  * PARAMS
322  *   pfnalloc [I]  A pointer to a function which allocates ram.  Uses
323  *                 the same interface as malloc.
324  *   pfnfree  [I]  A pointer to a function which frees ram.  Uses the
325  *                 same interface as free.
326  *   pfnopen  [I]  A pointer to a function which opens a file.  Uses
327  *                 the same interface as _open.
328  *   pfnread  [I]  A pointer to a function which reads from a file into
329  *                 a caller-provided buffer.  Uses the same interface
330  *                 as _read
331  *   pfnwrite [I]  A pointer to a function which writes to a file from
332  *                 a caller-provided buffer.  Uses the same interface
333  *                 as _write.
334  *   pfnclose [I]  A pointer to a function which closes a file handle.
335  *                 Uses the same interface as _close.
336  *   pfnseek  [I]  A pointer to a function which seeks in a file.
337  *                 Uses the same interface as _lseek.
338  *   cpuType  [I]  The type of CPU; ignored in wine (recommended value:
339  *                 cpuUNKNOWN, aka -1).
340  *   perf     [IO] A pointer to an ERF structure.  When FDICreate
341  *                 returns an error condition, error information may
342  *                 be found here as well as from GetLastError.
343  *
344  * RETURNS
345  *   On success, returns an FDI handle of type HFDI.
346  *   On failure, the NULL file handle is returned. Error
347  *   info can be retrieved from perf.
348  *
349  * INCLUDES
350  *   fdi.h
351  * 
352  */
353 HFDI __cdecl FDICreate(
354         PFNALLOC pfnalloc,
355         PFNFREE  pfnfree,
356         PFNOPEN  pfnopen,
357         PFNREAD  pfnread,
358         PFNWRITE pfnwrite,
359         PFNCLOSE pfnclose,
360         PFNSEEK  pfnseek,
361         int      cpuType,
362         PERF     perf)
363 {
364   HFDI rv;
365 
366   TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, "
367         "pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
368         pfnalloc, pfnfree, pfnopen, pfnread, pfnwrite, pfnclose, pfnseek,
369         cpuType, perf);
370 
371   if ((!pfnalloc) || (!pfnfree)) {
372     perf->erfOper = FDIERROR_NONE;
373     perf->erfType = ERROR_BAD_ARGUMENTS;
374     perf->fError = TRUE;
375 
376     SetLastError(ERROR_BAD_ARGUMENTS);
377     return NULL;
378   }
379 
380   if (!((rv = (*pfnalloc)(sizeof(FDI_Int))))) {
381     perf->erfOper = FDIERROR_ALLOC_FAIL;
382     perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
383     perf->fError = TRUE;
384 
385     SetLastError(ERROR_NOT_ENOUGH_MEMORY);
386     return NULL;
387   }
388   
389   PFDI_INT(rv)->FDI_Intmagic = FDI_INT_MAGIC;
390   PFDI_INT(rv)->pfnalloc = pfnalloc;
391   PFDI_INT(rv)->pfnfree = pfnfree;
392   PFDI_INT(rv)->pfnopen = pfnopen;
393   PFDI_INT(rv)->pfnread = pfnread;
394   PFDI_INT(rv)->pfnwrite = pfnwrite;
395   PFDI_INT(rv)->pfnclose = pfnclose;
396   PFDI_INT(rv)->pfnseek = pfnseek;
397   /* no-brainer: we ignore the cpu type; this is only used
398      for the 16-bit versions in Windows anyhow... */
399   PFDI_INT(rv)->perf = perf;
400 
401   return rv;
402 }
403 
404 /*******************************************************************
405  * FDI_getoffset (internal)
406  *
407  * returns the file pointer position of a file handle.
408  */
409 static long FDI_getoffset(HFDI hfdi, INT_PTR hf)
410 {
411   return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
412 }
413 
414 /**********************************************************************
415  * FDI_read_string (internal)
416  *
417  * allocate and read an arbitrarily long string from the cabinet
418  */
419 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
420 {
421   size_t len=256,
422          base = FDI_getoffset(hfdi, hf),
423          maxlen = cabsize - base;
424   BOOL ok = FALSE;
425   unsigned int i;
426   cab_UBYTE *buf = NULL;
427 
428   TRACE("(hfdi == ^%p, hf == %ld, cabsize == %ld)\n", hfdi, hf, cabsize);
429 
430   do {
431     if (len > maxlen) len = maxlen;
432     if (!(buf = PFDI_ALLOC(hfdi, len))) break;
433     if (!PFDI_READ(hfdi, hf, buf, len)) break;
434 
435     /* search for a null terminator in what we've just read */
436     for (i=0; i < len; i++) {
437       if (!buf[i]) {ok=TRUE; break;}
438     }
439 
440     if (!ok) {
441       if (len == maxlen) {
442         ERR("cabinet is truncated\n");
443         break;
444       }
445       /* The buffer is too small for the string. Reset the file to the point
446        * were we started, free the buffer and increase the size for the next try
447        */
448       PFDI_SEEK(hfdi, hf, base, SEEK_SET);
449       PFDI_FREE(hfdi, buf);
450       buf = NULL;
451       len *= 2;
452     }
453   } while (!ok);
454 
455   if (!ok) {
456     if (buf)
457       PFDI_FREE(hfdi, buf);
458     else
459       ERR("out of memory!\n");
460     return NULL;
461   }
462 
463   /* otherwise, set the stream to just after the string and return */
464   PFDI_SEEK(hfdi, hf, base + strlen((char *)buf) + 1, SEEK_SET);
465 
466   return (char *) buf;
467 }
468 
469 /******************************************************************
470  * FDI_read_entries (internal)
471  *
472  * process the cabinet header in the style of FDIIsCabinet, but
473  * without the sanity checks (and bug)
474  */
475 static BOOL FDI_read_entries(
476         HFDI             hfdi,
477         INT_PTR          hf,
478         PFDICABINETINFO  pfdici,
479         PMORE_ISCAB_INFO pmii)
480 {
481   int num_folders, num_files, header_resv, folder_resv = 0;
482   LONG base_offset, cabsize;
483   USHORT setid, cabidx, flags;
484   cab_UBYTE buf[64], block_resv;
485   char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
486 
487   TRACE("(hfdi == ^%p, hf == %ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
488 
489   /* 
490    * FIXME: I just noticed that I am memorizing the initial file pointer
491    * offset and restoring it before reading in the rest of the header
492    * information in the cabinet.  Perhaps that's correct -- that is, perhaps
493    * this API is supposed to support "streaming" cabinets which are embedded
494    * in other files, or cabinets which begin at file offsets other than zero.
495    * Otherwise, I should instead go to the absolute beginning of the file.
496    * (Either way, the semantics of wine's FDICopy require me to leave the
497    * file pointer where it is afterwards -- If Windows does not do so, we
498    * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
499    * 
500    * So, the answer lies in Windows; will native cabinet.dll recognize a
501    * cabinet "file" embedded in another file?  Note that cabextract.c does
502    * support this, which implies that Microsoft's might.  I haven't tried it
503    * yet so I don't know.  ATM, most of wine's FDI cabinet routines (except
504    * this one) would not work in this way.  To fix it, we could just make the
505    * various references to absolute file positions in the code relative to an
506    * initial "beginning" offset.  Because the FDICopy API doesn't take a
507    * file-handle like this one, we would therein need to search through the
508    * file for the beginning of the cabinet (as we also do in cabextract.c).
509    * Note that this limits us to a maximum of one cabinet per. file: the first.
510    *
511    * So, in summary: either the code below is wrong, or the rest of fdi.c is
512    * wrong... I cannot imagine that both are correct ;)  One of these flaws
513    * should be fixed after determining the behavior on Windows.   We ought
514    * to check both FDIIsCabinet and FDICopy for the right behavior.
515    *
516    * -gmt
517    */
518 
519   /* get basic offset & size info */
520   base_offset = FDI_getoffset(hfdi, hf);
521 
522   if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
523     if (pmii) {
524       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
525       PFDI_INT(hfdi)->perf->erfType = 0;
526       PFDI_INT(hfdi)->perf->fError = TRUE;
527     }
528     return FALSE;
529   }
530 
531   cabsize = FDI_getoffset(hfdi, hf);
532 
533   if ((cabsize == -1) || (base_offset == -1) || 
534       ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
535     if (pmii) {
536       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
537       PFDI_INT(hfdi)->perf->erfType = 0;
538       PFDI_INT(hfdi)->perf->fError = TRUE;
539     }
540     return FALSE;
541   }
542 
543   /* read in the CFHEADER */
544   if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
545     if (pmii) {
546       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
547       PFDI_INT(hfdi)->perf->erfType = 0;
548       PFDI_INT(hfdi)->perf->fError = TRUE;
549     }
550     return FALSE;
551   }
552   
553   /* check basic MSCF signature */
554   if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
555     if (pmii) {
556       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
557       PFDI_INT(hfdi)->perf->erfType = 0;
558       PFDI_INT(hfdi)->perf->fError = TRUE;
559     }
560     return FALSE;
561   }
562 
563   /* get the number of folders */
564   num_folders = EndGetI16(buf+cfhead_NumFolders);
565   if (num_folders == 0) {
566     /* PONDERME: is this really invalid? */
567     WARN("weird cabinet detect failure: no folders in cabinet\n");
568     if (pmii) {
569       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
570       PFDI_INT(hfdi)->perf->erfType = 0;
571       PFDI_INT(hfdi)->perf->fError = TRUE;
572     }
573     return FALSE;
574   }
575 
576   /* get the number of files */
577   num_files = EndGetI16(buf+cfhead_NumFiles);
578   if (num_files == 0) {
579     /* PONDERME: is this really invalid? */
580     WARN("weird cabinet detect failure: no files in cabinet\n");
581     if (pmii) {
582       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
583       PFDI_INT(hfdi)->perf->erfType = 0;
584       PFDI_INT(hfdi)->perf->fError = TRUE;
585     }
586     return FALSE;
587   }
588 
589   /* setid */
590   setid = EndGetI16(buf+cfhead_SetID);
591 
592   /* cabinet (set) index */
593   cabidx = EndGetI16(buf+cfhead_CabinetIndex);
594 
595   /* check the header revision */
596   if ((buf[cfhead_MajorVersion] > 1) ||
597       (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
598   {
599     WARN("cabinet format version > 1.3\n");
600     if (pmii) {
601       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
602       PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
603       PFDI_INT(hfdi)->perf->fError = TRUE;
604     }
605     return FALSE;
606   }
607 
608   /* pull the flags out */
609   flags = EndGetI16(buf+cfhead_Flags);
610 
611   /* read the reserved-sizes part of header, if present */
612   if (flags & cfheadRESERVE_PRESENT) {
613     if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
614       ERR("bunk reserve-sizes?\n");
615       if (pmii) {
616         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
617         PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
618         PFDI_INT(hfdi)->perf->fError = TRUE;
619       }
620       return FALSE;
621     }
622 
623     header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
624     if (pmii) pmii->header_resv = header_resv;
625     folder_resv = buf[cfheadext_FolderReserved];
626     if (pmii) pmii->folder_resv = folder_resv;
627     block_resv  = buf[cfheadext_DataReserved];
628     if (pmii) pmii->block_resv = block_resv;
629 
630     if (header_resv > 60000) {
631       WARN("WARNING; header reserved space > 60000\n");
632     }
633 
634     /* skip the reserved header */
635     if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
636       ERR("seek failure: header_resv\n");
637       if (pmii) {
638         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
639         PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
640         PFDI_INT(hfdi)->perf->fError = TRUE;
641       }
642       return FALSE;
643     }
644   }
645 
646   if (flags & cfheadPREV_CABINET) {
647     prevname = FDI_read_string(hfdi, hf, cabsize);
648     if (!prevname) {
649       if (pmii) {
650         PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
651         PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
652         PFDI_INT(hfdi)->perf->fError = TRUE;
653       }
654       return FALSE;
655     } else
656       if (pmii)
657         pmii->prevname = prevname;
658       else
659         PFDI_FREE(hfdi, prevname);
660     previnfo = FDI_read_string(hfdi, hf, cabsize);
661     if (previnfo) {
662       if (pmii) 
663         pmii->previnfo = previnfo;
664       else
665         PFDI_FREE(hfdi, previnfo);
666     }
667   }
668 
669   if (flags & cfheadNEXT_CABINET) {
670     if (pmii)
671       pmii->hasnext = TRUE;
672     nextname = FDI_read_string(hfdi, hf, cabsize);
673     if (!nextname) {
674       if ((flags & cfheadPREV_CABINET) && pmii) {
675         if (pmii->prevname) PFDI_FREE(hfdi, prevname);
676         if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
677       }
678       PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
679       PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
680       PFDI_INT(hfdi)->perf->fError = TRUE;
681       return FALSE;
682     } else
683       if (pmii)
684         pmii->nextname = nextname;
685       else
686         PFDI_FREE(hfdi, nextname);
687     nextinfo = FDI_read_string(hfdi, hf, cabsize);
688     if (nextinfo) {
689       if (pmii)
690         pmii->nextinfo = nextinfo;
691       else
692         PFDI_FREE(hfdi, nextinfo);
693     }
694   }
695 
696   /* we could process the whole cabinet searching for problems;
697      instead lets stop here.  Now let's fill out the paperwork */
698   pfdici->cbCabinet = cabsize;
699   pfdici->cFolders  = num_folders;
700   pfdici->cFiles    = num_files;
701   pfdici->setID     = setid;
702   pfdici->iCabinet  = cabidx;
703   pfdici->fReserve  = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
704   pfdici->hasprev   = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
705   pfdici->hasnext   = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
706   return TRUE;
707 }
708 
709 /***********************************************************************
710  *              FDIIsCabinet (CABINET.21)
711  *
712  * Informs the caller as to whether or not the provided file handle is
713  * really a cabinet or not, filling out the provided PFDICABINETINFO
714  * structure with information about the cabinet.  Brief explanations of
715  * the elements of this structure are available as comments accompanying
716  * its definition in wine's include/fdi.h.
717  *
718  * PARAMS
719  *   hfdi   [I]  An HFDI from FDICreate
720  *   hf     [I]  The file handle about which the caller inquires
721  *   pfdici [IO] Pointer to a PFDICABINETINFO structure which will
722  *               be filled out with information about the cabinet
723  *               file indicated by hf if, indeed, it is determined
724  *               to be a cabinet.
725  * 
726  * RETURNS
727  *   TRUE  if the file is a cabinet.  The info pointed to by pfdici will
728  *         be provided.
729  *   FALSE if the file is not a cabinet, or if an error was encountered
730  *         while processing the cabinet.  The PERF structure provided to
731  *         FDICreate can be queried for more error information.
732  *
733  * INCLUDES
734  *   fdi.c
735  */
736 BOOL __cdecl FDIIsCabinet(
737         HFDI            hfdi,
738         INT_PTR         hf,
739         PFDICABINETINFO pfdici)
740 {
741   BOOL rv;
742 
743   TRACE("(hfdi == ^%p, hf == ^%ld, pfdici == ^%p)\n", hfdi, hf, pfdici);
744 
745   if (!REALLY_IS_FDI(hfdi)) {
746     ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
747     SetLastError(ERROR_INVALID_HANDLE);
748     return FALSE;
749   }
750 
751   if (!hf) {
752     ERR("(!hf)!\n");
753     /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
754     PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
755     PFDI_INT(hfdi)->perf->fError = TRUE; */
756     SetLastError(ERROR_INVALID_HANDLE);
757     return FALSE;
758   }
759 
760   if (!pfdici) {
761     ERR("(!pfdici)!\n");
762     /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
763     PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
764     PFDI_INT(hfdi)->perf->fError = TRUE; */
765     SetLastError(ERROR_BAD_ARGUMENTS);
766     return FALSE;
767   }
768   rv = FDI_read_entries(hfdi, hf, pfdici, NULL); 
769 
770   if (rv)
771     pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
772 
773   return rv;
774 }
775 
776 /******************************************************************
777  * QTMfdi_initmodel (internal)
778  *
779  * Initialize a model which decodes symbols from [s] to [s]+[n]-1
780  */
781 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
782   int i;
783   m->shiftsleft = 4;
784   m->entries    = n;
785   m->syms       = sym;
786   memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
787   for (i = 0; i < n; i++) {
788     m->tabloc[i+s]     = i;   /* set up a look-up entry for symbol */
789     m->syms[i].sym     = i+s; /* actual symbol */
790     m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
791   }
792   m->syms[n].cumfreq = 0;
793 }
794 
795 /******************************************************************
796  * QTMfdi_init (internal)
797  */
798 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
799   unsigned int wndsize = 1 << window;
800   int msz = window * 2, i;
801   cab_ULONG j;
802 
803   /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
804   /* if a previously allocated window is big enough, keep it    */
805   if (window < 10 || window > 21) return DECR_DATAFORMAT;
806   if (QTM(actual_size) < wndsize) {
807     if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
808     QTM(window) = NULL;
809   }
810   if (!QTM(window)) {
811     if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
812     QTM(actual_size) = wndsize;
813   }
814   QTM(window_size) = wndsize;
815   QTM(window_posn) = 0;
816 
817   /* initialize static slot/extrabits tables */
818   for (i = 0, j = 0; i < 27; i++) {
819     CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
820     CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
821   }
822   for (i = 0, j = 0; i < 42; i++) {
823     CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
824     CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
825   }
826 
827   /* initialize arithmetic coding models */
828 
829   QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
830 
831   QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
832   QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
833   QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
834   QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
835 
836   /* model 4 depends on table size, ranges from 20 to 24  */
837   QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
838   /* model 5 depends on table size, ranges from 20 to 36  */
839   QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
840   /* model 6pos depends on table size, ranges from 20 to 42 */
841   QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
842   QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
843 
844   return DECR_OK;
845 }
846 
847 /************************************************************
848  * LZXfdi_init (internal)
849  */
850 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
851   static const cab_UBYTE bits[]  =
852                         { 0,  0,  0,  0,  1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,
853                           7,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
854                          15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
855                          17, 17, 17};
856   static const cab_ULONG base[] =
857                 {      0,       1,       2,       3,       4,       6,       8,      12,
858                       16,      24,      32,      48,      64,      96,     128,     192,
859                      256,     384,     512,     768,    1024,    1536,    2048,    3072,
860                     4096,    6144,    8192,   12288,   16384,   24576,   32768,   49152,
861                    65536,   98304,  131072,  196608,  262144,  393216,  524288,  655360,
862                   786432,  917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
863                  1835008, 1966080, 2097152};
864   cab_ULONG wndsize = 1 << window;
865   int posn_slots;
866 
867   /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
868   /* if a previously allocated window is big enough, keep it     */
869   if (window < 15 || window > 21) return DECR_DATAFORMAT;
870   if (LZX(actual_size) < wndsize) {
871     if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
872     LZX(window) = NULL;
873   }
874   if (!LZX(window)) {
875     if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
876     LZX(actual_size) = wndsize;
877   }
878   LZX(window_size) = wndsize;
879 
880   /* initialize static tables */
881   memcpy(CAB(extra_bits), bits, sizeof(bits));
882   memcpy(CAB(lzx_position_base), base, sizeof(base));
883 
884   /* calculate required position slots */
885   if (window == 20) posn_slots = 42;
886   else if (window == 21) posn_slots = 50;
887   else posn_slots = window << 1;
888 
889   /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
890 
891   LZX(R0)  =  LZX(R1)  = LZX(R2) = 1;
892   LZX(main_elements)   = LZX_NUM_CHARS + (posn_slots << 3);
893   LZX(header_read)     = 0;
894   LZX(frames_read)     = 0;
895   LZX(block_remaining) = 0;
896   LZX(block_type)      = LZX_BLOCKTYPE_INVALID;
897   LZX(intel_curpos)    = 0;
898   LZX(intel_started)   = 0;
899   LZX(window_posn)     = 0;
900 
901   /* initialize tables to 0 (because deltas will be applied to them) */
902   memset(LZX(MAINTREE_len), 0, sizeof(LZX(MAINTREE_len)));
903   memset(LZX(LENGTH_len), 0, sizeof(LZX(LENGTH_len)));
904 
905   return DECR_OK;
906 }
907 
908 /****************************************************
909  * NONEfdi_decomp(internal)
910  */
911 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
912 {
913   if (inlen != outlen) return DECR_ILLEGALDATA;
914   memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
915   return DECR_OK;
916 }
917 
918 /********************************************************
919  * Ziphuft_free (internal)
920  */
921 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
922 {
923   register struct Ziphuft *p, *q;
924 
925   /* Go through linked list, freeing from the allocated (t[-1]) address. */
926   p = t;
927   while (p != (struct Ziphuft *)NULL)
928   {
929     q = (--p)->v.t;
930     PFDI_FREE(hfdi, p);
931     p = q;
932   } 
933 }
934 
935 /*********************************************************
936  * fdi_Ziphuft_build (internal)
937  */
938 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, const cab_UWORD *d, const cab_UWORD *e,
939 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
940 {
941   cab_ULONG a;                          /* counter for codes of length k */
942   cab_ULONG el;                         /* length of EOB code (value 256) */
943   cab_ULONG f;                          /* i repeats in table every f entries */
944   cab_LONG g;                           /* maximum code length */
945   cab_LONG h;                           /* table level */
946   register cab_ULONG i;                 /* counter, current code */
947   register cab_ULONG j;                 /* counter */
948   register cab_LONG k;                  /* number of bits in current code */
949   cab_LONG *l;                          /* stack of bits per table */
950   register cab_ULONG *p;                /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
951   register struct Ziphuft *q;           /* points to current table */
952   struct Ziphuft r;                     /* table entry for structure assignment */
953   register cab_LONG w;                  /* bits before this table == (l * h) */
954   cab_ULONG *xp;                        /* pointer into x */
955   cab_LONG y;                           /* number of dummy codes added */
956   cab_ULONG z;                          /* number of entries in current table */
957 
958   l = ZIP(lx)+1;
959 
960   /* Generate counts for each bit length */
961   el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
962 
963   for(i = 0; i < ZIPBMAX+1; ++i)
964     ZIP(c)[i] = 0;
965   p = b;  i = n;
966   do
967   {
968     ZIP(c)[*p]++; p++;               /* assume all entries <= ZIPBMAX */
969   } while (--i);
970   if (ZIP(c)[0] == n)                /* null input--all zero length codes */
971   {
972     *t = (struct Ziphuft *)NULL;
973     *m = 0;
974     return 0;