oledlg: Updated Korean resource.
[wine/hacks.git] / dlls / cabinet / fdi.c
blobed520e8a6f72619e190d0178c643f70f2ec93589
1 /*
2 * File Decompression Interface
4 * Copyright 2000-2002 Stuart Caie
5 * Copyright 2002 Patrik Stridvall
6 * Copyright 2003 Greg Turner
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.
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.
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
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.
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.
37 * TODO:
39 * Wine does not implement the AFAIK undocumented "enumerate" callback during
40 * FDICopy. It is implemented in Windows and therefore worth investigating...
42 * Lots of pointers flying around here... am I leaking RAM?
44 * WTF is FDITruncate?
46 * Probably, I need to weed out some dead code-paths.
48 * Test unit(s).
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.
55 * FDICopy and fdi_decomp are incomprehensibly large; separating these into smaller
56 * functions would be nice.
58 * -gmt
61 #include "config.h"
63 #include <stdarg.h>
64 #include <stdio.h>
66 #include "windef.h"
67 #include "winbase.h"
68 #include "winerror.h"
69 #include "fdi.h"
70 #include "cabinet.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
76 THOSE_ZIP_CONSTS;
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 */
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 */
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.
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;
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.
122 typedef struct fdi_cds_fwd {
123 void *hfdi; /* the hfdi we are using */
124 int filehf, cabhf; /* file handle we are using */
125 struct fdi_folder *current; /* current folder we're extracting from */
126 cab_ULONG offset; /* uncompressed offset within folder */
127 cab_UBYTE *outpos; /* (high level) start of data to use up */
128 cab_UWORD outlen; /* (high level) amount of data to use up */
129 int (*decompress)(int, int, struct fdi_cds_fwd *); /* chosen compress fn */
130 cab_UBYTE inbuf[CAB_INPUTMAX+2]; /* +2 for lzx bitbuffer overflows! */
131 cab_UBYTE outbuf[CAB_BLOCKMAX];
132 union {
133 struct ZIPstate zip;
134 struct QTMstate qtm;
135 struct LZXstate lzx;
136 } methods;
137 /* some temp variables for use during decompression */
138 cab_UBYTE q_length_base[27], q_length_extra[27], q_extra_bits[42];
139 cab_ULONG q_position_base[42];
140 cab_ULONG lzx_position_base[51];
141 cab_UBYTE extra_bits[51];
142 USHORT setID; /* Cabinet set ID */
143 USHORT iCabinet; /* Cabinet number in set (0 based) */
144 struct fdi_cds_fwd *decomp_cab;
145 MORE_ISCAB_INFO mii;
146 struct fdi_folder *firstfol;
147 struct fdi_file *firstfile;
148 struct fdi_cds_fwd *next;
149 } fdi_decomp_state;
151 /****************************************************************
152 * QTMupdatemodel (internal)
154 void QTMupdatemodel(struct QTMmodel *model, int sym) {
155 struct QTMmodelsym temp;
156 int i, j;
158 for (i = 0; i < sym; i++) model->syms[i].cumfreq += 8;
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;
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;
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
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;
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;
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;
206 /*************************************************************************
207 * make_decode_table (internal)
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.
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.
219 * RETURNS
220 * OK: 0
221 * error: 1
223 int make_decode_table(cab_ULONG nsyms, cab_ULONG nbits, 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 */
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;
239 if((pos += bit_mask) > table_mask) return 1; /* table overrun */
241 /* fill all possible lookups of this symbol with the symbol itself */
242 fill = bit_mask;
243 while (fill-- > 0) table[leaf++] = sym;
246 bit_mask >>= 1;
247 bit_num++;
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;
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;
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++;
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++;
275 table[leaf] = sym;
277 if ((pos += bit_mask) > table_mask) return 1; /* table overflow */
280 bit_mask >>= 1;
281 bit_num++;
285 /* full table? */
286 if (pos == table_mask) return 0;
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;
293 /*************************************************************************
294 * checksum (internal)
296 cab_ULONG checksum(cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum) {
297 int len;
298 cab_ULONG ul = 0;
300 for (len = bytes >> 2; len--; data += 4) {
301 csum ^= ((data[0]) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24));
304 switch (bytes & 3) {
305 case 3: ul |= *data++ << 16;
306 case 2: ul |= *data++ << 8;
307 case 1: ul |= *data;
309 csum ^= ul;
311 return csum;
314 /***********************************************************************
315 * FDICreate (CABINET.20)
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.
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.
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.
349 * INCLUDES
350 * fdi.h
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)
364 HFDI rv;
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);
371 if ((!pfnalloc) || (!pfnfree)) {
372 perf->erfOper = FDIERROR_NONE;
373 perf->erfType = ERROR_BAD_ARGUMENTS;
374 perf->fError = TRUE;
376 SetLastError(ERROR_BAD_ARGUMENTS);
377 return NULL;
380 if (!((rv = ((HFDI) (*pfnalloc)(sizeof(FDI_Int)))))) {
381 perf->erfOper = FDIERROR_ALLOC_FAIL;
382 perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
383 perf->fError = TRUE;
385 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
386 return NULL;
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;
401 return rv;
404 /*******************************************************************
405 * FDI_getoffset (internal)
407 * returns the file pointer position of a file handle.
409 static long FDI_getoffset(HFDI hfdi, INT_PTR hf)
411 return PFDI_SEEK(hfdi, hf, 0L, SEEK_CUR);
414 /**********************************************************************
415 * FDI_realloc (internal)
417 * we can't use _msize; the user might not be using malloc, so we require
418 * an explicit specification of the previous size. inefficient.
420 static void *FDI_realloc(HFDI hfdi, void *mem, size_t prevsize, size_t newsize)
422 void *rslt = NULL;
423 char *irslt, *imem;
424 size_t copysize = (prevsize < newsize) ? prevsize : newsize;
425 if (prevsize == newsize) return mem;
426 rslt = PFDI_ALLOC(hfdi, newsize);
427 if (rslt)
428 for (irslt = (char *)rslt, imem = (char *)mem; (copysize); copysize--)
429 *irslt++ = *imem++;
430 PFDI_FREE(hfdi, mem);
431 return rslt;
434 /**********************************************************************
435 * FDI_read_string (internal)
437 * allocate and read an arbitrarily long string from the cabinet
439 static char *FDI_read_string(HFDI hfdi, INT_PTR hf, long cabsize)
441 size_t len=256,
442 oldlen = 0,
443 base = FDI_getoffset(hfdi, hf),
444 maxlen = cabsize - base;
445 BOOL ok = FALSE;
446 unsigned int i;
447 cab_UBYTE *buf = NULL;
449 TRACE("(hfdi == ^%p, hf == %d)\n", hfdi, hf);
451 do {
452 if (len > maxlen) len = maxlen;
453 if (!(buf = FDI_realloc(hfdi, buf, oldlen, len))) break;
454 oldlen = len;
455 if (!PFDI_READ(hfdi, hf, buf, len)) break;
457 /* search for a null terminator in what we've just read */
458 for (i=0; i < len; i++) {
459 if (!buf[i]) {ok=TRUE; break;}
462 if (!ok) {
463 if (len == maxlen) {
464 ERR("cabinet is truncated\n");
465 break;
467 len += 256;
468 PFDI_SEEK(hfdi, hf, base, SEEK_SET);
470 } while (!ok);
472 if (!ok) {
473 if (buf)
474 PFDI_FREE(hfdi, buf);
475 else
476 ERR("out of memory!\n");
477 return NULL;
480 /* otherwise, set the stream to just after the string and return */
481 PFDI_SEEK(hfdi, hf, base + ((cab_off_t) strlen((char *) buf)) + 1, SEEK_SET);
483 return (char *) buf;
486 /******************************************************************
487 * FDI_read_entries (internal)
489 * process the cabinet header in the style of FDIIsCabinet, but
490 * without the sanity checks (and bug)
492 static BOOL FDI_read_entries(
493 HFDI hfdi,
494 INT_PTR hf,
495 PFDICABINETINFO pfdici,
496 PMORE_ISCAB_INFO pmii)
498 int num_folders, num_files, header_resv, folder_resv = 0;
499 LONG base_offset, cabsize;
500 USHORT setid, cabidx, flags;
501 cab_UBYTE buf[64], block_resv;
502 char *prevname = NULL, *previnfo = NULL, *nextname = NULL, *nextinfo = NULL;
504 TRACE("(hfdi == ^%p, hf == %d, pfdici == ^%p)\n", hfdi, hf, pfdici);
507 * FIXME: I just noticed that I am memorizing the initial file pointer
508 * offset and restoring it before reading in the rest of the header
509 * information in the cabinet. Perhaps that's correct -- that is, perhaps
510 * this API is supposed to support "streaming" cabinets which are embedded
511 * in other files, or cabinets which begin at file offsets other than zero.
512 * Otherwise, I should instead go to the absolute beginning of the file.
513 * (Either way, the semantics of wine's FDICopy require me to leave the
514 * file pointer where it is afterwards -- If Windows does not do so, we
515 * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
517 * So, the answer lies in Windows; will native cabinet.dll recognize a
518 * cabinet "file" embedded in another file? Note that cabextract.c does
519 * support this, which implies that Microsoft's might. I haven't tried it
520 * yet so I don't know. ATM, most of wine's FDI cabinet routines (except
521 * this one) would not work in this way. To fix it, we could just make the
522 * various references to absolute file positions in the code relative to an
523 * initial "beginning" offset. Because the FDICopy API doesn't take a
524 * file-handle like this one, we would therein need to search through the
525 * file for the beginning of the cabinet (as we also do in cabextract.c).
526 * Note that this limits us to a maximum of one cabinet per. file: the first.
528 * So, in summary: either the code below is wrong, or the rest of fdi.c is
529 * wrong... I cannot imagine that both are correct ;) One of these flaws
530 * should be fixed after determining the behavior on Windows. We ought
531 * to check both FDIIsCabinet and FDICopy for the right behavior.
533 * -gmt
536 /* get basic offset & size info */
537 base_offset = FDI_getoffset(hfdi, hf);
539 if (PFDI_SEEK(hfdi, hf, 0, SEEK_END) == -1) {
540 if (pmii) {
541 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
542 PFDI_INT(hfdi)->perf->erfType = 0;
543 PFDI_INT(hfdi)->perf->fError = TRUE;
545 return FALSE;
548 cabsize = FDI_getoffset(hfdi, hf);
550 if ((cabsize == -1) || (base_offset == -1) ||
551 ( PFDI_SEEK(hfdi, hf, base_offset, SEEK_SET) == -1 )) {
552 if (pmii) {
553 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
554 PFDI_INT(hfdi)->perf->erfType = 0;
555 PFDI_INT(hfdi)->perf->fError = TRUE;
557 return FALSE;
560 /* read in the CFHEADER */
561 if (PFDI_READ(hfdi, hf, buf, cfhead_SIZEOF) != cfhead_SIZEOF) {
562 if (pmii) {
563 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
564 PFDI_INT(hfdi)->perf->erfType = 0;
565 PFDI_INT(hfdi)->perf->fError = TRUE;
567 return FALSE;
570 /* check basic MSCF signature */
571 if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) {
572 if (pmii) {
573 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
574 PFDI_INT(hfdi)->perf->erfType = 0;
575 PFDI_INT(hfdi)->perf->fError = TRUE;
577 return FALSE;
580 /* get the number of folders */
581 num_folders = EndGetI16(buf+cfhead_NumFolders);
582 if (num_folders == 0) {
583 /* PONDERME: is this really invalid? */
584 WARN("weird cabinet detect failure: no folders in cabinet\n");
585 if (pmii) {
586 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
587 PFDI_INT(hfdi)->perf->erfType = 0;
588 PFDI_INT(hfdi)->perf->fError = TRUE;
590 return FALSE;
593 /* get the number of files */
594 num_files = EndGetI16(buf+cfhead_NumFiles);
595 if (num_files == 0) {
596 /* PONDERME: is this really invalid? */
597 WARN("weird cabinet detect failure: no files in cabinet\n");
598 if (pmii) {
599 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NOT_A_CABINET;
600 PFDI_INT(hfdi)->perf->erfType = 0;
601 PFDI_INT(hfdi)->perf->fError = TRUE;
603 return FALSE;
606 /* setid */
607 setid = EndGetI16(buf+cfhead_SetID);
609 /* cabinet (set) index */
610 cabidx = EndGetI16(buf+cfhead_CabinetIndex);
612 /* check the header revision */
613 if ((buf[cfhead_MajorVersion] > 1) ||
614 (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3))
616 WARN("cabinet format version > 1.3\n");
617 if (pmii) {
618 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_UNKNOWN_CABINET_VERSION;
619 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
620 PFDI_INT(hfdi)->perf->fError = TRUE;
622 return FALSE;
625 /* pull the flags out */
626 flags = EndGetI16(buf+cfhead_Flags);
628 /* read the reserved-sizes part of header, if present */
629 if (flags & cfheadRESERVE_PRESENT) {
630 if (PFDI_READ(hfdi, hf, buf, cfheadext_SIZEOF) != cfheadext_SIZEOF) {
631 ERR("bunk reserve-sizes?\n");
632 if (pmii) {
633 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
634 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
635 PFDI_INT(hfdi)->perf->fError = TRUE;
637 return FALSE;
640 header_resv = EndGetI16(buf+cfheadext_HeaderReserved);
641 if (pmii) pmii->header_resv = header_resv;
642 folder_resv = buf[cfheadext_FolderReserved];
643 if (pmii) pmii->folder_resv = folder_resv;
644 block_resv = buf[cfheadext_DataReserved];
645 if (pmii) pmii->block_resv = block_resv;
647 if (header_resv > 60000) {
648 WARN("WARNING; header reserved space > 60000\n");
651 /* skip the reserved header */
652 if ((header_resv) && (PFDI_SEEK(hfdi, hf, header_resv, SEEK_CUR) == -1)) {
653 ERR("seek failure: header_resv\n");
654 if (pmii) {
655 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
656 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
657 PFDI_INT(hfdi)->perf->fError = TRUE;
659 return FALSE;
663 if (flags & cfheadPREV_CABINET) {
664 prevname = FDI_read_string(hfdi, hf, cabsize);
665 if (!prevname) {
666 if (pmii) {
667 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
668 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
669 PFDI_INT(hfdi)->perf->fError = TRUE;
671 return FALSE;
672 } else
673 if (pmii)
674 pmii->prevname = prevname;
675 else
676 PFDI_FREE(hfdi, prevname);
677 previnfo = FDI_read_string(hfdi, hf, cabsize);
678 if (previnfo) {
679 if (pmii)
680 pmii->previnfo = previnfo;
681 else
682 PFDI_FREE(hfdi, previnfo);
686 if (flags & cfheadNEXT_CABINET) {
687 if (pmii)
688 pmii->hasnext = TRUE;
689 nextname = FDI_read_string(hfdi, hf, cabsize);
690 if (!nextname) {
691 if ((flags & cfheadPREV_CABINET) && pmii) {
692 if (pmii->prevname) PFDI_FREE(hfdi, prevname);
693 if (pmii->previnfo) PFDI_FREE(hfdi, previnfo);
695 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
696 PFDI_INT(hfdi)->perf->erfType = 0; /* ? */
697 PFDI_INT(hfdi)->perf->fError = TRUE;
698 return FALSE;
699 } else
700 if (pmii)
701 pmii->nextname = nextname;
702 else
703 PFDI_FREE(hfdi, nextname);
704 nextinfo = FDI_read_string(hfdi, hf, cabsize);
705 if (nextinfo) {
706 if (pmii)
707 pmii->nextinfo = nextinfo;
708 else
709 PFDI_FREE(hfdi, nextinfo);
713 /* we could process the whole cabinet searching for problems;
714 instead lets stop here. Now let's fill out the paperwork */
715 pfdici->cbCabinet = cabsize;
716 pfdici->cFolders = num_folders;
717 pfdici->cFiles = num_files;
718 pfdici->setID = setid;
719 pfdici->iCabinet = cabidx;
720 pfdici->fReserve = (flags & cfheadRESERVE_PRESENT) ? TRUE : FALSE;
721 pfdici->hasprev = (flags & cfheadPREV_CABINET) ? TRUE : FALSE;
722 pfdici->hasnext = (flags & cfheadNEXT_CABINET) ? TRUE : FALSE;
723 return TRUE;
726 /***********************************************************************
727 * FDIIsCabinet (CABINET.21)
729 * Informs the caller as to whether or not the provided file handle is
730 * really a cabinet or not, filling out the provided PFDICABINETINFO
731 * structure with information about the cabinet. Brief explanations of
732 * the elements of this structure are available as comments accompanying
733 * its definition in wine's include/fdi.h.
735 * PARAMS
736 * hfdi [I] An HFDI from FDICreate
737 * hf [I] The file handle about which the caller inquires
738 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
739 * be filled out with information about the cabinet
740 * file indicated by hf if, indeed, it is determined
741 * to be a cabinet.
743 * RETURNS
744 * TRUE if the file is a cabinet. The info pointed to by pfdici will
745 * be provided.
746 * FALSE if the file is not a cabinet, or if an error was encountered
747 * while processing the cabinet. The PERF structure provided to
748 * FDICreate can be queried for more error information.
750 * INCLUDES
751 * fdi.c
753 BOOL __cdecl FDIIsCabinet(
754 HFDI hfdi,
755 INT_PTR hf,
756 PFDICABINETINFO pfdici)
758 BOOL rv;
760 TRACE("(hfdi == ^%p, hf == ^%d, pfdici == ^%p)\n", hfdi, hf, pfdici);
762 if (!REALLY_IS_FDI(hfdi)) {
763 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi);
764 SetLastError(ERROR_INVALID_HANDLE);
765 return FALSE;
768 if (!hf) {
769 ERR("(!hf)!\n");
770 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
771 PFDI_INT(hfdi)->perf->erfType = ERROR_INVALID_HANDLE;
772 PFDI_INT(hfdi)->perf->fError = TRUE; */
773 SetLastError(ERROR_INVALID_HANDLE);
774 return FALSE;
777 if (!pfdici) {
778 ERR("(!pfdici)!\n");
779 /* PFDI_INT(hfdi)->perf->erfOper = FDIERROR_NONE;
780 PFDI_INT(hfdi)->perf->erfType = ERROR_BAD_ARGUMENTS;
781 PFDI_INT(hfdi)->perf->fError = TRUE; */
782 SetLastError(ERROR_BAD_ARGUMENTS);
783 return FALSE;
785 rv = FDI_read_entries(hfdi, hf, pfdici, NULL);
787 if (rv)
788 pfdici->hasnext = FALSE; /* yuck. duplicate apparent cabinet.dll bug */
790 return rv;
793 /******************************************************************
794 * QTMfdi_initmodel (internal)
796 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
798 static void QTMfdi_initmodel(struct QTMmodel *m, struct QTMmodelsym *sym, int n, int s) {
799 int i;
800 m->shiftsleft = 4;
801 m->entries = n;
802 m->syms = sym;
803 memset(m->tabloc, 0xFF, sizeof(m->tabloc)); /* clear out look-up table */
804 for (i = 0; i < n; i++) {
805 m->tabloc[i+s] = i; /* set up a look-up entry for symbol */
806 m->syms[i].sym = i+s; /* actual symbol */
807 m->syms[i].cumfreq = n-i; /* current frequency of that symbol */
809 m->syms[n].cumfreq = 0;
812 /******************************************************************
813 * QTMfdi_init (internal)
815 static int QTMfdi_init(int window, int level, fdi_decomp_state *decomp_state) {
816 unsigned int wndsize = 1 << window;
817 int msz = window * 2, i;
818 cab_ULONG j;
820 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
821 /* if a previously allocated window is big enough, keep it */
822 if (window < 10 || window > 21) return DECR_DATAFORMAT;
823 if (QTM(actual_size) < wndsize) {
824 if (QTM(window)) PFDI_FREE(CAB(hfdi), QTM(window));
825 QTM(window) = NULL;
827 if (!QTM(window)) {
828 if (!(QTM(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
829 QTM(actual_size) = wndsize;
831 QTM(window_size) = wndsize;
832 QTM(window_posn) = 0;
834 /* initialize static slot/extrabits tables */
835 for (i = 0, j = 0; i < 27; i++) {
836 CAB(q_length_extra)[i] = (i == 26) ? 0 : (i < 2 ? 0 : i - 2) >> 2;
837 CAB(q_length_base)[i] = j; j += 1 << ((i == 26) ? 5 : CAB(q_length_extra)[i]);
839 for (i = 0, j = 0; i < 42; i++) {
840 CAB(q_extra_bits)[i] = (i < 2 ? 0 : i-2) >> 1;
841 CAB(q_position_base)[i] = j; j += 1 << CAB(q_extra_bits)[i];
844 /* initialize arithmetic coding models */
846 QTMfdi_initmodel(&QTM(model7), &QTM(m7sym)[0], 7, 0);
848 QTMfdi_initmodel(&QTM(model00), &QTM(m00sym)[0], 0x40, 0x00);
849 QTMfdi_initmodel(&QTM(model40), &QTM(m40sym)[0], 0x40, 0x40);
850 QTMfdi_initmodel(&QTM(model80), &QTM(m80sym)[0], 0x40, 0x80);
851 QTMfdi_initmodel(&QTM(modelC0), &QTM(mC0sym)[0], 0x40, 0xC0);
853 /* model 4 depends on table size, ranges from 20 to 24 */
854 QTMfdi_initmodel(&QTM(model4), &QTM(m4sym)[0], (msz < 24) ? msz : 24, 0);
855 /* model 5 depends on table size, ranges from 20 to 36 */
856 QTMfdi_initmodel(&QTM(model5), &QTM(m5sym)[0], (msz < 36) ? msz : 36, 0);
857 /* model 6pos depends on table size, ranges from 20 to 42 */
858 QTMfdi_initmodel(&QTM(model6pos), &QTM(m6psym)[0], msz, 0);
859 QTMfdi_initmodel(&QTM(model6len), &QTM(m6lsym)[0], 27, 0);
861 return DECR_OK;
864 /************************************************************
865 * LZXfdi_init (internal)
867 static int LZXfdi_init(int window, fdi_decomp_state *decomp_state) {
868 cab_ULONG wndsize = 1 << window;
869 int i, j, posn_slots;
871 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
872 /* if a previously allocated window is big enough, keep it */
873 if (window < 15 || window > 21) return DECR_DATAFORMAT;
874 if (LZX(actual_size) < wndsize) {
875 if (LZX(window)) PFDI_FREE(CAB(hfdi), LZX(window));
876 LZX(window) = NULL;
878 if (!LZX(window)) {
879 if (!(LZX(window) = PFDI_ALLOC(CAB(hfdi), wndsize))) return DECR_NOMEMORY;
880 LZX(actual_size) = wndsize;
882 LZX(window_size) = wndsize;
884 /* initialize static tables */
885 for (i=0, j=0; i <= 50; i += 2) {
886 CAB(extra_bits)[i] = CAB(extra_bits)[i+1] = j; /* 0,0,0,0,1,1,2,2,3,3... */
887 if ((i != 0) && (j < 17)) j++; /* 0,0,1,2,3,4...15,16,17,17,17,17... */
889 for (i=0, j=0; i <= 50; i++) {
890 CAB(lzx_position_base)[i] = j; /* 0,1,2,3,4,6,8,12,16,24,32,... */
891 j += 1 << CAB(extra_bits)[i]; /* 1,1,1,1,2,2,4,4,8,8,16,16,32,32,... */
894 /* calculate required position slots */
895 if (window == 20) posn_slots = 42;
896 else if (window == 21) posn_slots = 50;
897 else posn_slots = window << 1;
899 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
901 LZX(R0) = LZX(R1) = LZX(R2) = 1;
902 LZX(main_elements) = LZX_NUM_CHARS + (posn_slots << 3);
903 LZX(header_read) = 0;
904 LZX(frames_read) = 0;
905 LZX(block_remaining) = 0;
906 LZX(block_type) = LZX_BLOCKTYPE_INVALID;
907 LZX(intel_curpos) = 0;
908 LZX(intel_started) = 0;
909 LZX(window_posn) = 0;
911 /* initialize tables to 0 (because deltas will be applied to them) */
912 for (i = 0; i < LZX_MAINTREE_MAXSYMBOLS; i++) LZX(MAINTREE_len)[i] = 0;
913 for (i = 0; i < LZX_LENGTH_MAXSYMBOLS; i++) LZX(LENGTH_len)[i] = 0;
915 return DECR_OK;
918 /****************************************************
919 * NONEfdi_decomp(internal)
921 static int NONEfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
923 if (inlen != outlen) return DECR_ILLEGALDATA;
924 memcpy(CAB(outbuf), CAB(inbuf), (size_t) inlen);
925 return DECR_OK;
928 /********************************************************
929 * Ziphuft_free (internal)
931 static void fdi_Ziphuft_free(HFDI hfdi, struct Ziphuft *t)
933 register struct Ziphuft *p, *q;
935 /* Go through linked list, freeing from the allocated (t[-1]) address. */
936 p = t;
937 while (p != (struct Ziphuft *)NULL)
939 q = (--p)->v.t;
940 PFDI_FREE(hfdi, p);
941 p = q;
945 /*********************************************************
946 * fdi_Ziphuft_build (internal)
948 static cab_LONG fdi_Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, cab_UWORD *d, cab_UWORD *e,
949 struct Ziphuft **t, cab_LONG *m, fdi_decomp_state *decomp_state)
951 cab_ULONG a; /* counter for codes of length k */
952 cab_ULONG el; /* length of EOB code (value 256) */
953 cab_ULONG f; /* i repeats in table every f entries */
954 cab_LONG g; /* maximum code length */
955 cab_LONG h; /* table level */
956 register cab_ULONG i; /* counter, current code */
957 register cab_ULONG j; /* counter */
958 register cab_LONG k; /* number of bits in current code */
959 cab_LONG *l; /* stack of bits per table */
960 register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
961 register struct Ziphuft *q; /* points to current table */
962 struct Ziphuft r; /* table entry for structure assignment */
963 register cab_LONG w; /* bits before this table == (l * h) */
964 cab_ULONG *xp; /* pointer into x */
965 cab_LONG y; /* number of dummy codes added */
966 cab_ULONG z; /* number of entries in current table */
968 l = ZIP(lx)+1;
970 /* Generate counts for each bit length */
971 el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */
973 for(i = 0; i < ZIPBMAX+1; ++i)
974 ZIP(c)[i] = 0;
975 p = b; i = n;
978 ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */
979 } while (--i);
980 if (ZIP(c)[0] == n) /* null input--all zero length codes */
982 *t = (struct Ziphuft *)NULL;
983 *m = 0;
984 return 0;
987 /* Find minimum and maximum length, bound *m by those */
988 for (j = 1; j <= ZIPBMAX; j++)
989 if (ZIP(c)[j])
990 break;
991 k = j; /* minimum code length */
992 if ((cab_ULONG)*m < j)
993 *m = j;
994 for (i = ZIPBMAX; i; i--)
995 if (ZIP(c)[i])
996 break;
997 g = i; /* maximum code length */
998 if ((cab_ULONG)*m > i)
999 *m = i;
1001 /* Adjust last length count to fill out codes, if needed */
1002 for (y = 1 << j; j < i; j++, y <<= 1)
1003 if ((y -= ZIP(c)[j]) < 0)
1004 return 2; /* bad input: more codes than bits */
1005 if ((y -= ZIP(c)[i]) < 0)
1006 return 2;
1007 ZIP(c)[i] += y;
1009 /* Generate starting offsets LONGo the value table for each length */
1010 ZIP(x)[1] = j = 0;
1011 p = ZIP(c) + 1; xp = ZIP(x) + 2;
1012 while (--i)
1013 { /* note that i == g from above */
1014 *xp++ = (j += *p++);
1017 /* Make a table of values in order of bit lengths */
1018 p = b; i = 0;
1020 if ((j = *p++) != 0)
1021 ZIP(v)[ZIP(x)[j]++] = i;
1022 } while (++i < n);
1025 /* Generate the Huffman codes and for each, make the table entries */
1026 ZIP(x)[0] = i = 0; /* first Huffman code is zero */
1027 p = ZIP(v); /* grab values in bit order */
1028 h = -1; /* no tables yet--level -1 */
1029 w = l[-1] = 0; /* no bits decoded yet */
1030 ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */
1031 q = (struct Ziphuft *)NULL; /* ditto */
1032 z = 0; /* ditto */
1034 /* go through the bit lengths (k already is bits in shortest code) */
1035 for (; k <= g; k++)
1037 a = ZIP(c)[k];
1038 while (a--)
1040 /* here i is the Huffman code of length k bits for value *p */
1041 /* make tables up to required level */
1042 while (k > w + l[h])
1044 w += l[h++]; /* add bits already decoded */
1046 /* compute minimum size table less than or equal to *m bits */
1047 z = (z = g - w) > (cab_ULONG)*m ? *m : z; /* upper limit */
1048 if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
1049 { /* too few codes for k-w bit table */
1050 f -= a + 1; /* deduct codes from patterns left */
1051 xp = ZIP(c) + k;
1052 while (++j < z) /* try smaller tables up to z bits */
1054 if ((f <<= 1) <= *++xp)
1055 break; /* enough codes to use up j bits */
1056 f -= *xp; /* else deduct codes from patterns */
1059 if ((cab_ULONG)w + j > el && (cab_ULONG)w < el)
1060 j = el - w; /* make EOB code end at table */
1061 z = 1 << j; /* table entries for j-bit table */
1062 l[h] = j; /* set table size in stack */
1064 /* allocate and link in new table */
1065 if (!(q = (struct Ziphuft *) PFDI_ALLOC(CAB(hfdi), (z + 1)*sizeof(struct Ziphuft))))
1067 if(h)
1068 fdi_Ziphuft_free(CAB(hfdi), ZIP(u)[0]);
1069 return 3; /* not enough memory */
1071 *t = q + 1; /* link to list for Ziphuft_free() */
1072 *(t = &(q->v.t)) = (struct Ziphuft *)NULL;
1073 ZIP(u)[h] = ++q; /* table starts after link */
1075 /* connect to last table, if there is one */
1076 if (h)
1078 ZIP(x)[h] = i; /* save pattern for backing up */
1079 r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */
1080 r.e = (cab_UBYTE)(16 + j); /* bits in this table */
1081 r.v.t = q; /* pointer to this table */
1082 j = (i & ((1 << w) - 1)) >> (w - l[h-1]);
1083 ZIP(u)[h-1][j] = r; /* connect to last table */
1087 /* set up table entry in r */
1088 r.b = (cab_UBYTE)(k - w);
1089 if (p >= ZIP(v) + n)
1090 r.e = 99; /* out of values--invalid code */
1091 else if (*p < s)
1093 r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */
1094 r.v.n = *p++; /* simple code is just the value */
1096 else
1098 r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */
1099 r.v.n = d[*p++ - s];
1102 /* fill code-like entries with r */
1103 f = 1 << (k - w);
1104 for (j = i >> w; j < z; j += f)
1105 q[j] = r;
1107 /* backwards increment the k-bit code i */
1108 for (j = 1 << (k - 1); i & j; j >>= 1)
1109 i ^= j;
1110 i ^= j;
1112 /* backup over finished tables */
1113 while ((i & ((1 << w) - 1)) != ZIP(x)[h])
1114 w -= l[--h]; /* don't need to update q */
1118 /* return actual size of base table */
1119 *m = l[0];
1121 /* Return true (1) if we were given an incomplete table */
1122 return y != 0 && g != 1;
1125 /*********************************************************
1126 * fdi_Zipinflate_codes (internal)
1128 cab_LONG fdi_Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td,
1129 cab_LONG bl, cab_LONG bd, fdi_decomp_state *decomp_state)
1131 register cab_ULONG e; /* table entry flag/number of extra bits */
1132 cab_ULONG n, d; /* length and index for copy */
1133 cab_ULONG w; /* current window position */
1134 struct Ziphuft *t; /* pointer to table entry */
1135 cab_ULONG ml, md; /* masks for bl and bd bits */
1136 register cab_ULONG b; /* bit buffer */
1137 register cab_ULONG k; /* number of bits in bit buffer */
1139 /* make local copies of globals */
1140 b = ZIP(bb); /* initialize bit buffer */
1141 k = ZIP(bk);
1142 w = ZIP(window_posn); /* initialize window position */
1144 /* inflate the coded data */
1145 ml = Zipmask[bl]; /* precompute masks for speed */
1146 md = Zipmask[bd];
1148 for(;;)
1150 ZIPNEEDBITS((cab_ULONG)bl)
1151 if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16)
1154 if (e == 99)
1155 return 1;
1156 ZIPDUMPBITS(t->b)
1157 e -= 16;
1158 ZIPNEEDBITS(e)
1159 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
1160 ZIPDUMPBITS(t->b)
1161 if (e == 16) /* then it's a literal */
1162 CAB(outbuf)[w++] = (cab_UBYTE)t->v.n;
1163 else /* it's an EOB or a length */
1165 /* exit if end of block */
1166 if(e == 15)
1167 break;
1169 /* get length of block to copy */
1170 ZIPNEEDBITS(e)
1171 n = t->v.n + ((cab_ULONG)b & Zipmask[e]);
1172 ZIPDUMPBITS(e);
1174 /* decode distance of block to copy */
1175 ZIPNEEDBITS((cab_ULONG)bd)
1176 if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16)
1177 do {
1178 if (e == 99)
1179 return 1;
1180 ZIPDUMPBITS(t->b)
1181 e -= 16;
1182 ZIPNEEDBITS(e)
1183 } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16);
1184 ZIPDUMPBITS(t->b)
1185 ZIPNEEDBITS(e)
1186 d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]);
1187 ZIPDUMPBITS(e)
1190 n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e);
1193 CAB(outbuf)[w++] = CAB(outbuf)[d++];
1194 } while (--e);
1195 } while (n);
1199 /* restore the globals from the locals */
1200 ZIP(window_posn) = w; /* restore global window pointer */
1201 ZIP(bb) = b; /* restore global bit buffer */
1202 ZIP(bk) = k;
1204 /* done */
1205 return 0;
1208 /***********************************************************
1209 * Zipinflate_stored (internal)
1211 static cab_LONG fdi_Zipinflate_stored(fdi_decomp_state *decomp_state)
1212 /* "decompress" an inflated type 0 (stored) block. */
1214 cab_ULONG n; /* number of bytes in block */
1215 cab_ULONG w; /* current window position */
1216 register cab_ULONG b; /* bit buffer */
1217 register cab_ULONG k; /* number of bits in bit buffer */
1219 /* make local copies of globals */
1220 b = ZIP(bb); /* initialize bit buffer */
1221 k = ZIP(bk);
1222 w = ZIP(window_posn); /* initialize window position */
1224 /* go to byte boundary */
1225 n = k & 7;
1226 ZIPDUMPBITS(n);
1228 /* get the length and its complement */
1229 ZIPNEEDBITS(16)
1230 n = ((cab_ULONG)b & 0xffff);
1231 ZIPDUMPBITS(16)
1232 ZIPNEEDBITS(16)
1233 if (n != (cab_ULONG)((~b) & 0xffff))
1234 return 1; /* error in compressed data */
1235 ZIPDUMPBITS(16)
1237 /* read and output the compressed data */
1238 while(n--)
1240 ZIPNEEDBITS(8)
1241 CAB(outbuf)[w++] = (cab_UBYTE)b;
1242 ZIPDUMPBITS(8)
1245 /* restore the globals from the locals */
1246 ZIP(window_posn) = w; /* restore global window pointer */
1247 ZIP(bb) = b; /* restore global bit buffer */
1248 ZIP(bk) = k;
1249 return 0;
1252 /******************************************************
1253 * fdi_Zipinflate_fixed (internal)
1255 static cab_LONG fdi_Zipinflate_fixed(fdi_decomp_state *decomp_state)
1257 struct Ziphuft *fixed_tl;
1258 struct Ziphuft *fixed_td;
1259 cab_LONG fixed_bl, fixed_bd;
1260 cab_LONG i; /* temporary variable */
1261 cab_ULONG *l;
1263 l = ZIP(ll);
1265 /* literal table */
1266 for(i = 0; i < 144; i++)
1267 l[i] = 8;
1268 for(; i < 256; i++)
1269 l[i] = 9;
1270 for(; i < 280; i++)
1271 l[i] = 7;
1272 for(; i < 288; i++) /* make a complete, but wrong code set */
1273 l[i] = 8;
1274 fixed_bl = 7;
1275 if((i = fdi_Ziphuft_build(l, 288, 257, (cab_UWORD *) Zipcplens,
1276 (cab_UWORD *) Zipcplext, &fixed_tl, &fixed_bl, decomp_state)))
1277 return i;
1279 /* distance table */
1280 for(i = 0; i < 30; i++) /* make an incomplete code set */
1281 l[i] = 5;
1282 fixed_bd = 5;
1283 if((i = fdi_Ziphuft_build(l, 30, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
1284 &fixed_td, &fixed_bd, decomp_state)) > 1)
1286 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1287 return i;
1290 /* decompress until an end-of-block code */
1291 i = fdi_Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state);
1293 fdi_Ziphuft_free(CAB(hfdi), fixed_td);
1294 fdi_Ziphuft_free(CAB(hfdi), fixed_tl);
1295 return i;
1298 /**************************************************************
1299 * fdi_Zipinflate_dynamic (internal)
1301 static cab_LONG fdi_Zipinflate_dynamic(fdi_decomp_state *decomp_state)
1302 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1304 cab_LONG i; /* temporary variables */
1305 cab_ULONG j;
1306 cab_ULONG *ll;
1307 cab_ULONG l; /* last length */
1308 cab_ULONG m; /* mask for bit lengths table */
1309 cab_ULONG n; /* number of lengths to get */
1310 struct Ziphuft *tl; /* literal/length code table */
1311 struct Ziphuft *td; /* distance code table */
1312 cab_LONG bl; /* lookup bits for tl */
1313 cab_LONG bd; /* lookup bits for td */
1314 cab_ULONG nb; /* number of bit length codes */
1315 cab_ULONG nl; /* number of literal/length codes */
1316 cab_ULONG nd; /* number of distance codes */
1317 register cab_ULONG b; /* bit buffer */
1318 register cab_ULONG k; /* number of bits in bit buffer */
1320 /* make local bit buffer */
1321 b = ZIP(bb);
1322 k = ZIP(bk);
1323 ll = ZIP(ll);
1325 /* read in table lengths */
1326 ZIPNEEDBITS(5)
1327 nl = 257 + ((cab_ULONG)b & 0x1f); /* number of literal/length codes */
1328 ZIPDUMPBITS(5)
1329 ZIPNEEDBITS(5)
1330 nd = 1 + ((cab_ULONG)b & 0x1f); /* number of distance codes */
1331 ZIPDUMPBITS(5)
1332 ZIPNEEDBITS(4)
1333 nb = 4 + ((cab_ULONG)b & 0xf); /* number of bit length codes */
1334 ZIPDUMPBITS(4)
1335 if(nl > 288 || nd > 32)
1336 return 1; /* bad lengths */
1338 /* read in bit-length-code lengths */
1339 for(j = 0; j < nb; j++)
1341 ZIPNEEDBITS(3)
1342 ll[Zipborder[j]] = (cab_ULONG)b & 7;
1343 ZIPDUMPBITS(3)
1345 for(; j < 19; j++)
1346 ll[Zipborder[j]] = 0;
1348 /* build decoding table for trees--single level, 7 bit lookup */
1349 bl = 7;
1350 if((i = fdi_Ziphuft_build(ll, 19, 19, NULL, NULL, &tl, &bl, decomp_state)) != 0)
1352 if(i == 1)
1353 fdi_Ziphuft_free(CAB(hfdi), tl);
1354 return i; /* incomplete code set */
1357 /* read in literal and distance code lengths */
1358 n = nl + nd;
1359 m = Zipmask[bl];
1360 i = l = 0;
1361 while((cab_ULONG)i < n)
1363 ZIPNEEDBITS((cab_ULONG)bl)
1364 j = (td = tl + ((cab_ULONG)b & m))->b;
1365 ZIPDUMPBITS(j)
1366 j = td->v.n;
1367 if (j < 16) /* length of code in bits (0..15) */
1368 ll[i++] = l = j; /* save last length in l */
1369 else if (j == 16) /* repeat last length 3 to 6 times */
1371 ZIPNEEDBITS(2)
1372 j = 3 + ((cab_ULONG)b & 3);
1373 ZIPDUMPBITS(2)
1374 if((cab_ULONG)i + j > n)
1375 return 1;
1376 while (j--)
1377 ll[i++] = l;
1379 else if (j == 17) /* 3 to 10 zero length codes */
1381 ZIPNEEDBITS(3)
1382 j = 3 + ((cab_ULONG)b & 7);
1383 ZIPDUMPBITS(3)
1384 if ((cab_ULONG)i + j > n)
1385 return 1;
1386 while (j--)
1387 ll[i++] = 0;
1388 l = 0;
1390 else /* j == 18: 11 to 138 zero length codes */
1392 ZIPNEEDBITS(7)
1393 j = 11 + ((cab_ULONG)b & 0x7f);
1394 ZIPDUMPBITS(7)
1395 if ((cab_ULONG)i + j > n)
1396 return 1;
1397 while (j--)
1398 ll[i++] = 0;
1399 l = 0;
1403 /* free decoding table for trees */
1404 fdi_Ziphuft_free(CAB(hfdi), tl);
1406 /* restore the global bit buffer */
1407 ZIP(bb) = b;
1408 ZIP(bk) = k;
1410 /* build the decoding tables for literal/length and distance codes */
1411 bl = ZIPLBITS;
1412 if((i = fdi_Ziphuft_build(ll, nl, 257, (cab_UWORD *) Zipcplens, (cab_UWORD *) Zipcplext,
1413 &tl, &bl, decomp_state)) != 0)
1415 if(i == 1)
1416 fdi_Ziphuft_free(CAB(hfdi), tl);
1417 return i; /* incomplete code set */
1419 bd = ZIPDBITS;
1420 fdi_Ziphuft_build(ll + nl, nd, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext,
1421 &td, &bd, decomp_state);
1423 /* decompress until an end-of-block code */
1424 if(fdi_Zipinflate_codes(tl, td, bl, bd, decomp_state))
1425 return 1;
1427 /* free the decoding tables, return */
1428 fdi_Ziphuft_free(CAB(hfdi), tl);
1429 fdi_Ziphuft_free(CAB(hfdi), td);
1430 return 0;
1433 /*****************************************************
1434 * fdi_Zipinflate_block (internal)
1436 static cab_LONG fdi_Zipinflate_block(cab_LONG *e, fdi_decomp_state *decomp_state) /* e == last block flag */
1437 { /* decompress an inflated block */
1438 cab_ULONG t; /* block type */
1439 register cab_ULONG b; /* bit buffer */
1440 register cab_ULONG k; /* number of bits in bit buffer */
1442 /* make local bit buffer */
1443 b = ZIP(bb);
1444 k = ZIP(bk);
1446 /* read in last block bit */
1447 ZIPNEEDBITS(1)
1448 *e = (cab_LONG)b & 1;
1449 ZIPDUMPBITS(1)
1451 /* read in block type */
1452 ZIPNEEDBITS(2)
1453 t = (cab_ULONG)b & 3;
1454 ZIPDUMPBITS(2)
1456 /* restore the global bit buffer */
1457 ZIP(bb) = b;
1458 ZIP(bk) = k;
1460 /* inflate that block type */
1461 if(t == 2)
1462 return fdi_Zipinflate_dynamic(decomp_state);
1463 if(t == 0)
1464 return fdi_Zipinflate_stored(decomp_state);
1465 if(t == 1)
1466 return fdi_Zipinflate_fixed(decomp_state);
1467 /* bad block type */
1468 return 2;
1471 /****************************************************
1472 * ZIPfdi_decomp(internal)
1474 static int ZIPfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1476 cab_LONG e; /* last block flag */
1478 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1480 ZIP(inpos) = CAB(inbuf);
1481 ZIP(bb) = ZIP(bk) = ZIP(window_posn) = 0;
1482 if(outlen > ZIPWSIZE)
1483 return DECR_DATAFORMAT;
1485 /* CK = Chris Kirmse, official Microsoft purloiner */
1486 if(ZIP(inpos)[0] != 0x43 || ZIP(inpos)[1] != 0x4B)
1487 return DECR_ILLEGALDATA;
1488 ZIP(inpos) += 2;
1490 do {
1491 if(fdi_Zipinflate_block(&e, decomp_state))
1492 return DECR_ILLEGALDATA;
1493 } while(!e);
1495 /* return success */
1496 return DECR_OK;
1499 /*******************************************************************
1500 * QTMfdi_decomp(internal)
1502 static int QTMfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state)
1504 cab_UBYTE *inpos = CAB(inbuf);
1505 cab_UBYTE *window = QTM(window);
1506 cab_UBYTE *runsrc, *rundest;
1508 cab_ULONG window_posn = QTM(window_posn);
1509 cab_ULONG window_size = QTM(window_size);
1511 /* used by bitstream macros */
1512 register int bitsleft, bitrun, bitsneed;
1513 register cab_ULONG bitbuf;
1515 /* used by GET_SYMBOL */
1516 cab_ULONG range;
1517 cab_UWORD symf;
1518 int i;
1520 int extra, togo = outlen, match_length = 0, copy_length;
1521 cab_UBYTE selector, sym;
1522 cab_ULONG match_offset = 0;
1524 cab_UWORD H = 0xFFFF, L = 0, C;
1526 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1528 /* read initial value of C */
1529 Q_INIT_BITSTREAM;
1530 Q_READ_BITS(C, 16);
1532 /* apply 2^x-1 mask */
1533 window_posn &= window_size - 1;
1534 /* runs can't straddle the window wraparound */
1535 if ((window_posn + togo) > window_size) {
1536 TRACE("straddled run\n");
1537 return DECR_DATAFORMAT;
1540 while (togo > 0) {
1541 GET_SYMBOL(model7, selector);
1542 switch (selector) {
1543 case 0:
1544 GET_SYMBOL(model00, sym); window[window_posn++] = sym; togo--;
1545 break;
1546 case 1:
1547 GET_SYMBOL(model40, sym); window[window_posn++] = sym; togo--;
1548 break;
1549 case 2:
1550 GET_SYMBOL(model80, sym); window[window_posn++] = sym; togo--;
1551 break;
1552 case 3:
1553 GET_SYMBOL(modelC0, sym); window[window_posn++] = sym; togo--;
1554 break;
1556 case 4:
1557 /* selector 4 = fixed length of 3 */
1558 GET_SYMBOL(model4, sym);
1559 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1560 match_offset = CAB(q_position_base)[sym] + extra + 1;
1561 match_length = 3;
1562 break;
1564 case 5:
1565 /* selector 5 = fixed length of 4 */
1566 GET_SYMBOL(model5, sym);
1567 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1568 match_offset = CAB(q_position_base)[sym] + extra + 1;
1569 match_length = 4;
1570 break;
1572 case 6:
1573 /* selector 6 = variable length */
1574 GET_SYMBOL(model6len, sym);
1575 Q_READ_BITS(extra, CAB(q_length_extra)[sym]);
1576 match_length = CAB(q_length_base)[sym] + extra + 5;
1577 GET_SYMBOL(model6pos, sym);
1578 Q_READ_BITS(extra, CAB(q_extra_bits)[sym]);
1579 match_offset = CAB(q_position_base)[sym] + extra + 1;
1580 break;
1582 default:
1583 TRACE("Selector is bogus\n");
1584 return DECR_ILLEGALDATA;
1587 /* if this is a match */
1588 if (selector >= 4) {
1589 rundest = window + window_posn;
1590 togo -= match_length;
1592 /* copy any wrapped around source data */
1593 if (window_posn >= match_offset) {
1594 /* no wrap */
1595 runsrc = rundest - match_offset;
1596 } else {
1597 runsrc = rundest + (window_size - match_offset);
1598 copy_length = match_offset - window_posn;
1599 if (copy_length < match_length) {
1600 match_length -= copy_length;
1601 window_posn += copy_length;
1602 while (copy_length-- > 0) *rundest++ = *runsrc++;
1603 runsrc = window;
1606 window_posn += match_length;
1608 /* copy match data - no worries about destination wraps */
1609 while (match_length-- > 0) *rundest++ = *runsrc++;
1611 } /* while (togo > 0) */
1613 if (togo != 0) {
1614 TRACE("Frame overflow, this_run = %d\n", togo);
1615 return DECR_ILLEGALDATA;
1618 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1619 outlen, outlen);
1621 QTM(window_posn) = window_posn;
1622 return DECR_OK;
1625 /************************************************************
1626 * fdi_lzx_read_lens (internal)
1628 static int fdi_lzx_read_lens(cab_UBYTE *lens, cab_ULONG first, cab_ULONG last, struct lzx_bits *lb,
1629 fdi_decomp_state *decomp_state) {
1630 cab_ULONG i,j, x,y;
1631 int z;
1633 register cab_ULONG bitbuf = lb->bb;
1634 register int bitsleft = lb->bl;
1635 cab_UBYTE *inpos = lb->ip;
1636 cab_UWORD *hufftbl;
1638 for (x = 0; x < 20; x++) {
1639 READ_BITS(y, 4);
1640 LENTABLE(PRETREE)[x] = y;
1642 BUILD_TABLE(PRETREE);
1644 for (x = first; x < last; ) {
1645 READ_HUFFSYM(PRETREE, z);
1646 if (z == 17) {
1647 READ_BITS(y, 4); y += 4;
1648 while (y--) lens[x++] = 0;
1650 else if (z == 18) {
1651 READ_BITS(y, 5); y += 20;
1652 while (y--) lens[x++] = 0;
1654 else if (z == 19) {
1655 READ_BITS(y, 1); y += 4;
1656 READ_HUFFSYM(PRETREE, z);
1657 z = lens[x] - z; if (z < 0) z += 17;
1658 while (y--) lens[x++] = z;
1660 else {
1661 z = lens[x] - z; if (z < 0) z += 17;
1662 lens[x++] = z;
1666 lb->bb = bitbuf;
1667 lb->bl = bitsleft;
1668 lb->ip = inpos;
1669 return 0;
1672 /*******************************************************
1673 * LZXfdi_decomp(internal)
1675 static int LZXfdi_decomp(int inlen, int outlen, fdi_decomp_state *decomp_state) {
1676 cab_UBYTE *inpos = CAB(inbuf);
1677 cab_UBYTE *endinp = inpos + inlen;
1678 cab_UBYTE *window = LZX(window);
1679 cab_UBYTE *runsrc, *rundest;
1680 cab_UWORD *hufftbl; /* used in READ_HUFFSYM macro as chosen decoding table */
1682 cab_ULONG window_posn = LZX(window_posn);
1683 cab_ULONG window_size = LZX(window_size);
1684 cab_ULONG R0 = LZX(R0);
1685 cab_ULONG R1 = LZX(R1);
1686 cab_ULONG R2 = LZX(R2);
1688 register cab_ULONG bitbuf;
1689 register int bitsleft;
1690 cab_ULONG match_offset, i,j,k; /* ijk used in READ_HUFFSYM macro */
1691 struct lzx_bits lb; /* used in READ_LENGTHS macro */
1693 int togo = outlen, this_run, main_element, aligned_bits;
1694 int match_length, copy_length, length_footer, extra, verbatim_bits;
1696 TRACE("(inlen == %d, outlen == %d)\n", inlen, outlen);
1698 INIT_BITSTREAM;
1700 /* read header if necessary */
1701 if (!LZX(header_read)) {
1702 i = j = 0;
1703 READ_BITS(k, 1); if (k) { READ_BITS(i,16); READ_BITS(j,16); }
1704 LZX(intel_filesize) = (i << 16) | j; /* or 0 if not encoded */
1705 LZX(header_read) = 1;
1708 /* main decoding loop */
1709 while (togo > 0) {
1710 /* last block finished, new block expected */
1711 if (LZX(block_remaining) == 0) {
1712 if (LZX(block_type) == LZX_BLOCKTYPE_UNCOMPRESSED) {
1713 if (LZX(block_length) & 1) inpos++; /* realign bitstream to word */
1714 INIT_BITSTREAM;
1717 READ_BITS(LZX(block_type), 3);
1718 READ_BITS(i, 16);
1719 READ_BITS(j, 8);
1720 LZX(block_remaining) = LZX(block_length) = (i << 8) | j;
1722 switch (LZX(block_type)) {
1723 case LZX_BLOCKTYPE_ALIGNED:
1724 for (i = 0; i < 8; i++) { READ_BITS(j, 3); LENTABLE(ALIGNED)[i] = j; }
1725 BUILD_TABLE(ALIGNED);
1726 /* rest of aligned header is same as verbatim */
1728 case LZX_BLOCKTYPE_VERBATIM:
1729 READ_LENGTHS(MAINTREE, 0, 256, fdi_lzx_read_lens);
1730 READ_LENGTHS(MAINTREE, 256, LZX(main_elements), fdi_lzx_read_lens);
1731 BUILD_TABLE(MAINTREE);
1732 if (LENTABLE(MAINTREE)[0xE8] != 0) LZX(intel_started) = 1;
1734 READ_LENGTHS(LENGTH, 0, LZX_NUM_SECONDARY_LENGTHS, fdi_lzx_read_lens);
1735 BUILD_TABLE(LENGTH);
1736 break;
1738 case LZX_BLOCKTYPE_UNCOMPRESSED:
1739 LZX(intel_started) = 1; /* because we can't assume otherwise */
1740 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1741 if (bitsleft > 16) inpos -= 2; /* and align the bitstream! */
1742 R0 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1743 R1 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1744 R2 = inpos[0]|(inpos[1]<<8)|(inpos[2]<<16)|(inpos[3]<<24);inpos+=4;
1745 break;
1747 default:
1748 return DECR_ILLEGALDATA;
1752 /* buffer exhaustion check */
1753 if (inpos > endinp) {
1754 /* it's possible to have a file where the next run is less than
1755 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1756 * in building the tables will exhaust the buffer, so we should
1757 * allow for this, but not allow those accidentally read bits to
1758 * be used (so we check that there are at least 16 bits
1759 * remaining - in this boundary case they aren't really part of
1760 * the compressed data)
1762 if (inpos > (endinp+2) || bitsleft < 16) return DECR_ILLEGALDATA;
1765 while ((this_run = LZX(block_remaining)) > 0 && togo > 0) {
1766 if (this_run > togo) this_run = togo;
1767 togo -= this_run;
1768 LZX(block_remaining) -= this_run;
1770 /* apply 2^x-1 mask */
1771 window_posn &= window_size - 1;
1772 /* runs can't straddle the window wraparound */
1773 if ((window_posn + this_run) > window_size)
1774 return DECR_DATAFORMAT;
1776 switch (LZX(block_type)) {
1778 case LZX_BLOCKTYPE_VERBATIM:
1779 while (this_run > 0) {
1780 READ_HUFFSYM(MAINTREE, main_element);
1782 if (main_element < LZX_NUM_CHARS) {
1783 /* literal: 0 to LZX_NUM_CHARS-1 */
1784 window[window_posn++] = main_element;
1785 this_run--;
1787 else {
1788 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1789 main_element -= LZX_NUM_CHARS;
1791 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1792 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1793 READ_HUFFSYM(LENGTH, length_footer);
1794 match_length += length_footer;
1796 match_length += LZX_MIN_MATCH;
1798 match_offset = main_element >> 3;
1800 if (match_offset > 2) {
1801 /* not repeated offset */
1802 if (match_offset != 3) {
1803 extra = CAB(extra_bits)[match_offset];
1804 READ_BITS(verbatim_bits, extra);
1805 match_offset = CAB(lzx_position_base)[match_offset]
1806 - 2 + verbatim_bits;
1808 else {
1809 match_offset = 1;
1812 /* update repeated offset LRU queue */
1813 R2 = R1; R1 = R0; R0 = match_offset;
1815 else if (match_offset == 0) {
1816 match_offset = R0;
1818 else if (match_offset == 1) {
1819 match_offset = R1;
1820 R1 = R0; R0 = match_offset;
1822 else /* match_offset == 2 */ {
1823 match_offset = R2;
1824 R2 = R0; R0 = match_offset;
1827 rundest = window + window_posn;
1828 this_run -= match_length;
1830 /* copy any wrapped around source data */
1831 if (window_posn >= match_offset) {
1832 /* no wrap */
1833 runsrc = rundest - match_offset;
1834 } else {
1835 runsrc = rundest + (window_size - match_offset);
1836 copy_length = match_offset - window_posn;
1837 if (copy_length < match_length) {
1838 match_length -= copy_length;
1839 window_posn += copy_length;
1840 while (copy_length-- > 0) *rundest++ = *runsrc++;
1841 runsrc = window;
1844 window_posn += match_length;
1846 /* copy match data - no worries about destination wraps */
1847 while (match_length-- > 0) *rundest++ = *runsrc++;
1850 break;
1852 case LZX_BLOCKTYPE_ALIGNED:
1853 while (this_run > 0) {
1854 READ_HUFFSYM(MAINTREE, main_element);
1856 if (main_element < LZX_NUM_CHARS) {
1857 /* literal: 0 to LZX_NUM_CHARS-1 */
1858 window[window_posn++] = main_element;
1859 this_run--;
1861 else {
1862 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1863 main_element -= LZX_NUM_CHARS;
1865 match_length = main_element & LZX_NUM_PRIMARY_LENGTHS;
1866 if (match_length == LZX_NUM_PRIMARY_LENGTHS) {
1867 READ_HUFFSYM(LENGTH, length_footer);
1868 match_length += length_footer;
1870 match_length += LZX_MIN_MATCH;
1872 match_offset = main_element >> 3;
1874 if (match_offset > 2) {
1875 /* not repeated offset */
1876 extra = CAB(extra_bits)[match_offset];
1877 match_offset = CAB(lzx_position_base)[match_offset] - 2;
1878 if (extra > 3) {
1879 /* verbatim and aligned bits */
1880 extra -= 3;
1881 READ_BITS(verbatim_bits, extra);
1882 match_offset += (verbatim_bits << 3);
1883 READ_HUFFSYM(ALIGNED, aligned_bits);
1884 match_offset += aligned_bits;
1886 else if (extra == 3) {
1887 /* aligned bits only */
1888 READ_HUFFSYM(ALIGNED, aligned_bits);
1889 match_offset += aligned_bits;
1891 else if (extra > 0) { /* extra==1, extra==2 */
1892 /* verbatim bits only */
1893 READ_BITS(verbatim_bits, extra);
1894 match_offset += verbatim_bits;
1896 else /* extra == 0 */ {
1897 /* ??? */
1898 match_offset = 1;
1901 /* update repeated offset LRU queue */
1902 R2 = R1; R1 = R0; R0 = match_offset;
1904 else if (match_offset == 0) {
1905 match_offset = R0;
1907 else if (match_offset == 1) {
1908 match_offset = R1;
1909 R1 = R0; R0 = match_offset;
1911 else /* match_offset == 2 */ {
1912 match_offset = R2;
1913 R2 = R0; R0 = match_offset;
1916 rundest = window + window_posn;
1917 this_run -= match_length;
1919 /* copy any wrapped around source data */
1920 if (window_posn >= match_offset) {
1921 /* no wrap */
1922 runsrc = rundest - match_offset;
1923 } else {
1924 runsrc = rundest + (window_size - match_offset);
1925 copy_length = match_offset - window_posn;
1926 if (copy_length < match_length) {
1927 match_length -= copy_length;
1928 window_posn += copy_length;
1929 while (copy_length-- > 0) *rundest++ = *runsrc++;
1930 runsrc = window;
1933 window_posn += match_length;
1935 /* copy match data - no worries about destination wraps */
1936 while (match_length-- > 0) *rundest++ = *runsrc++;
1939 break;
1941 case LZX_BLOCKTYPE_UNCOMPRESSED:
1942 if ((inpos + this_run) > endinp) return DECR_ILLEGALDATA;
1943 memcpy(window + window_posn, inpos, (size_t) this_run);
1944 inpos += this_run; window_posn += this_run;
1945 break;
1947 default:
1948 return DECR_ILLEGALDATA; /* might as well */
1954 if (togo != 0) return DECR_ILLEGALDATA;
1955 memcpy(CAB(outbuf), window + ((!window_posn) ? window_size : window_posn) -
1956 outlen, (size_t) outlen);
1958 LZX(window_posn) = window_posn;
1959 LZX(R0) = R0;
1960 LZX(R1) = R1;
1961 LZX(R2) = R2;
1963 /* intel E8 decoding */
1964 if ((LZX(frames_read)++ < 32768) && LZX(intel_filesize) != 0) {
1965 if (outlen <= 6 || !LZX(intel_started)) {
1966 LZX(intel_curpos) += outlen;
1968 else {
1969 cab_UBYTE *data = CAB(outbuf);
1970 cab_UBYTE *dataend = data + outlen - 10;
1971 cab_LONG curpos = LZX(intel_curpos);
1972 cab_LONG filesize = LZX(intel_filesize);
1973 cab_LONG abs_off, rel_off;
1975 LZX(intel_curpos) = curpos + outlen;
1977 while (data < dataend) {
1978 if (*data++ != 0xE8) { curpos++; continue; }
1979 abs_off = data[0] | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
1980 if ((abs_off >= -curpos) && (abs_off < filesize)) {
1981 rel_off = (abs_off >= 0) ? abs_off - curpos : abs_off + filesize;
1982 data[0] = (cab_UBYTE) rel_off;
1983 data[1] = (cab_UBYTE) (rel_off >> 8);
1984 data[2] = (cab_UBYTE) (rel_off >> 16);
1985 data[3] = (cab_UBYTE) (rel_off >> 24);
1987 data += 4;
1988 curpos += 5;
1992 return DECR_OK;
1995 /**********************************************************
1996 * fdi_decomp (internal)
1998 * Decompress the requested number of bytes. If savemode is zero,
1999 * do not save the output anywhere, just plow through blocks until we
2000 * reach the specified (uncompressed) distance from the starting point,
2001 * and remember the position of the cabfile pointer (and which cabfile)
2002 * after we are done; otherwise, save the data out to CAB(filehf),
2003 * decompressing the requested number of bytes and writing them out. This
2004 * is also where we jump to additional cabinets in the case of split
2005 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
2007 static int fdi_decomp(struct fdi_file *fi, int savemode, fdi_decomp_state *decomp_state,
2008 char *pszCabPath, PFNFDINOTIFY pfnfdin, void *pvUser)
2010 cab_ULONG bytes = savemode ? fi->length : fi->offset - CAB(offset);
2011 cab_UBYTE buf[cfdata_SIZEOF], *data;
2012 cab_UWORD inlen, len, outlen, cando;
2013 cab_ULONG cksum;
2014 cab_LONG err;
2015 fdi_decomp_state *cab = (savemode && CAB(decomp_cab)) ? CAB(decomp_cab) : decomp_state;
2017 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi, savemode, bytes);
2019 while (bytes > 0) {
2020 /* cando = the max number of bytes we can do */
2021 cando = CAB(outlen);
2022 if (cando > bytes) cando = bytes;
2024 /* if cando != 0 */
2025 if (cando && savemode)
2026 PFDI_WRITE(CAB(hfdi), CAB(filehf), CAB(outpos), cando);
2028 CAB(outpos) += cando;
2029 CAB(outlen) -= cando;
2030 bytes -= cando; if (!bytes) break;
2032 /* we only get here if we emptied the output buffer */
2034 /* read data header + data */
2035 inlen = outlen = 0;
2036 while (outlen == 0) {
2037 /* read the block header, skip the reserved part */
2038 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf, cfdata_SIZEOF) != cfdata_SIZEOF)
2039 return DECR_INPUT;
2041 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.block_resv, SEEK_CUR) == -1)
2042 return DECR_INPUT;
2044 /* we shouldn't get blocks over CAB_INPUTMAX in size */
2045 data = CAB(inbuf) + inlen;
2046 len = EndGetI16(buf+cfdata_CompressedSize);
2047 inlen += len;
2048 if (inlen > CAB_INPUTMAX) return DECR_INPUT;
2049 if (PFDI_READ(CAB(hfdi), cab->cabhf, data, len) != len)
2050 return DECR_INPUT;
2052 /* clear two bytes after read-in data */
2053 data[len+1] = data[len+2] = 0;
2055 /* perform checksum test on the block (if one is stored) */
2056 cksum = EndGetI32(buf+cfdata_CheckSum);
2057 if (cksum && cksum != checksum(buf+4, 4, checksum(data, len, 0)))
2058 return DECR_CHECKSUM; /* checksum is wrong */
2060 outlen = EndGetI16(buf+cfdata_UncompressedSize);
2062 /* outlen=0 means this block was the last contiguous part
2063 of a split block, continued in the next cabinet */
2064 if (outlen == 0) {
2065 int pathlen, filenamelen, idx, i, cabhf;
2066 char fullpath[MAX_PATH], userpath[256];
2067 FDINOTIFICATION fdin;
2068 FDICABINETINFO fdici;
2069 char emptystring = '\0';
2070 cab_UBYTE buf2[64];
2071 int success = FALSE;
2072 struct fdi_folder *fol = NULL, *linkfol = NULL;
2073 struct fdi_file *file = NULL, *linkfile = NULL;
2075 tryanothercab:
2077 /* set up the next decomp_state... */
2078 if (!(cab->next)) {
2079 if (!cab->mii.hasnext) return DECR_INPUT;
2081 if (!((cab->next = PFDI_ALLOC(CAB(hfdi), sizeof(fdi_decomp_state)))))
2082 return DECR_NOMEMORY;
2084 ZeroMemory(cab->next, sizeof(fdi_decomp_state));
2086 /* copy pszCabPath to userpath */
2087 ZeroMemory(userpath, 256);
2088 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2089 if (pathlen) {
2090 if (pathlen < 256) {
2091 for (i = 0; i <= pathlen; i++)
2092 userpath[i] = pszCabPath[i];
2093 } /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2096 /* initial fdintNEXT_CABINET notification */
2097 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2098 fdin.psz1 = (cab->mii.nextname) ? cab->mii.nextname : &emptystring;
2099 fdin.psz2 = (cab->mii.nextinfo) ? cab->mii.nextinfo : &emptystring;
2100 fdin.psz3 = &userpath[0];
2101 fdin.fdie = FDIERROR_NONE;
2102 fdin.pv = pvUser;
2104 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2106 do {
2108 pathlen = (userpath) ? strlen(userpath) : 0;
2109 filenamelen = (cab->mii.nextname) ? strlen(cab->mii.nextname) : 0;
2111 /* slight overestimation here to save CPU cycles in the developer's brain */
2112 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2113 ERR("MAX_PATH exceeded.\n");
2114 return DECR_ILLEGALDATA;
2117 /* paste the path and filename together */
2118 idx = 0;
2119 if (pathlen) {
2120 for (i = 0; i < pathlen; i++) fullpath[idx++] = userpath[i];
2121 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2123 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = cab->mii.nextname[i];
2124 fullpath[idx] = '\0';
2126 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2128 /* try to get a handle to the cabfile */
2129 cabhf = PFDI_OPEN(CAB(hfdi), fullpath, 32768, _S_IREAD | _S_IWRITE);
2130 if (cabhf == -1) {
2131 /* no file. allow the user to try again */
2132 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2133 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2134 continue;
2137 if (cabhf == 0) {
2138 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2139 fdin.fdie = FDIERROR_CABINET_NOT_FOUND;
2140 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2141 continue;
2144 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2145 if (!FDI_read_entries(CAB(hfdi), cabhf, &fdici, &(cab->next->mii))) {
2146 WARN("FDIIsCabinet failed.\n");
2147 PFDI_CLOSE(CAB(hfdi), cabhf);
2148 fdin.fdie = FDIERROR_NOT_A_CABINET;
2149 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2150 continue;
2153 if ((fdici.setID != cab->setID) || (fdici.iCabinet != (cab->iCabinet + 1))) {
2154 WARN("Wrong Cabinet.\n");
2155 PFDI_CLOSE(CAB(hfdi), cabhf);
2156 fdin.fdie = FDIERROR_WRONG_CABINET;
2157 if (((*pfnfdin)(fdintNEXT_CABINET, &fdin))) return DECR_USERABORT;
2158 continue;
2161 break;
2163 } while (1);
2165 /* cabinet notification */
2166 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2167 fdin.setID = fdici.setID;
2168 fdin.iCabinet = fdici.iCabinet;
2169 fdin.pv = pvUser;
2170 fdin.psz1 = (cab->next->mii.nextname) ? cab->next->mii.nextname : &emptystring;
2171 fdin.psz2 = (cab->next->mii.nextinfo) ? cab->next->mii.nextinfo : &emptystring;
2172 fdin.psz3 = pszCabPath;
2174 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) return DECR_USERABORT;
2176 cab->next->setID = fdici.setID;
2177 cab->next->iCabinet = fdici.iCabinet;
2178 cab->next->hfdi = CAB(hfdi);
2179 cab->next->filehf = CAB(filehf);
2180 cab->next->cabhf = cabhf;
2181 cab->next->decompress = CAB(decompress); /* crude, but unused anyhow */
2183 cab = cab->next; /* advance to the next cabinet */
2185 /* read folders */
2186 for (i = 0; i < fdici.cFolders; i++) {
2187 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffold_SIZEOF) != cffold_SIZEOF)
2188 return DECR_INPUT;
2190 if (cab->mii.folder_resv > 0)
2191 PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->mii.folder_resv, SEEK_CUR);
2193 fol = (struct fdi_folder *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_folder));
2194 if (!fol) {
2195 ERR("out of memory!\n");
2196 return DECR_NOMEMORY;
2198 ZeroMemory(fol, sizeof(struct fdi_folder));
2199 if (!(cab->firstfol)) cab->firstfol = fol;
2201 fol->offset = (cab_off_t) EndGetI32(buf2+cffold_DataOffset);
2202 fol->num_blocks = EndGetI16(buf2+cffold_NumBlocks);
2203 fol->comp_type = EndGetI16(buf2+cffold_CompType);
2205 if (linkfol)
2206 linkfol->next = fol;
2207 linkfol = fol;
2210 /* read files */
2211 for (i = 0; i < fdici.cFiles; i++) {
2212 if (PFDI_READ(CAB(hfdi), cab->cabhf, buf2, cffile_SIZEOF) != cffile_SIZEOF)
2213 return DECR_INPUT;
2215 file = (struct fdi_file *) PFDI_ALLOC(CAB(hfdi), sizeof(struct fdi_file));
2216 if (!file) {
2217 ERR("out of memory!\n");
2218 return DECR_NOMEMORY;
2220 ZeroMemory(file, sizeof(struct fdi_file));
2221 if (!(cab->firstfile)) cab->firstfile = file;
2223 file->length = EndGetI32(buf2+cffile_UncompressedSize);
2224 file->offset = EndGetI32(buf2+cffile_FolderOffset);
2225 file->index = EndGetI16(buf2+cffile_FolderIndex);
2226 file->time = EndGetI16(buf2+cffile_Time);
2227 file->date = EndGetI16(buf2+cffile_Date);
2228 file->attribs = EndGetI16(buf2+cffile_Attribs);
2229 file->filename = FDI_read_string(CAB(hfdi), cab->cabhf, fdici.cbCabinet);
2231 if (!file->filename) return DECR_INPUT;
2233 if (linkfile)
2234 linkfile->next = file;
2235 linkfile = file;
2238 } else
2239 cab = cab->next; /* advance to the next cabinet */
2241 /* iterate files -- if we encounter the continued file, process it --
2242 otherwise, jump to the label above and keep looking */
2244 for (file = cab->firstfile; (file); file = file->next) {
2245 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2246 /* check to ensure a real match */
2247 if (strcasecmp(fi->filename, file->filename) == 0) {
2248 success = TRUE;
2249 if (PFDI_SEEK(CAB(hfdi), cab->cabhf, cab->firstfol->offset, SEEK_SET) == -1)
2250 return DECR_INPUT;
2251 break;
2255 if (!success) goto tryanothercab; /* FIXME: shouldn't this trigger
2256 "Wrong Cabinet" notification? */
2260 /* decompress block */
2261 if ((err = CAB(decompress)(inlen, outlen, decomp_state)))
2262 return err;
2263 CAB(outlen) = outlen;
2264 CAB(outpos) = CAB(outbuf);
2267 CAB(decomp_cab) = cab;
2268 return DECR_OK;
2271 /***********************************************************************
2272 * FDICopy (CABINET.22)
2274 * Iterates through the files in the Cabinet file indicated by name and
2275 * file-location. May chain forward to additional cabinets (typically
2276 * only one) if files which begin in this Cabinet are continued in another
2277 * cabinet. For each file which is partially contained in this cabinet,
2278 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2279 * notification to the pfnfdin callback. For each file which begins in
2280 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2281 * callback, and the file is optionally decompressed and saved to disk.
2282 * Notification is not provided for files which are not at least partially
2283 * contained in the specified cabinet file.
2285 * See below for a thorough explanation of the various notification
2286 * callbacks.
2288 * PARAMS
2289 * hfdi [I] An HFDI from FDICreate
2290 * pszCabinet [I] C-style string containing the filename of the cabinet
2291 * pszCabPath [I] C-style string containing the file path of the cabinet
2292 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2293 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2294 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2295 * value: NULL.
2296 * pvUser [I] arbitrary void * value which is passed to callbacks.
2298 * RETURNS
2299 * TRUE if successful.
2300 * FALSE if unsuccessful (error information is provided in the ERF structure
2301 * associated with the provided decompression handle by FDICreate).
2303 * CALLBACKS
2305 * Two pointers to callback functions are provided as parameters to FDICopy:
2306 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2307 * types are as follows:
2309 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2310 * PFDINOTIFICATION pfdin );
2312 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2314 * You can create functions of this type using the FNFDINOTIFY() and
2315 * FNFDIDECRYPT() macros, respectively. For example:
2317 * FNFDINOTIFY(mycallback) {
2318 * / * use variables fdint and pfdin to process notification * /
2321 * The second callback, which could be used for decrypting encrypted data,
2322 * is not used at all.
2324 * Each notification informs the user of some event which has occurred during
2325 * decompression of the cabinet file; each notification is also an opportunity
2326 * for the callee to abort decompression. The information provided to the
2327 * callback and the meaning of the callback's return value vary drastically
2328 * across the various types of notification. The type of notification is the
2329 * fdint parameter; all other information is provided to the callback in
2330 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2331 * pfdin. The only part of that structure which is assigned for every callback
2332 * is the pv element, which contains the arbitrary value which was passed to
2333 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2334 * is highly dependent on fdint).
2336 * If you encounter unknown notifications, you should return zero if you want
2337 * decompression to continue (or -1 to abort). All strings used in the
2338 * callbacks are regular C-style strings. Detailed descriptions of each
2339 * notification type follow:
2341 * fdintCABINET_INFO:
2343 * This is the first notification provided after calling FDICopy, and provides
2344 * the user with various information about the cabinet. Note that this is
2345 * called for each cabinet FDICopy opens, not just the first one. In the
2346 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2347 * next cabinet file in the set after the one just loaded (if any), psz2
2348 * contains a pointer to the name or "info" of the next disk, psz3
2349 * contains a pointer to the file-path of the current cabinet, setID
2350 * contains an arbitrary constant associated with this set of cabinet files,
2351 * and iCabinet contains the numerical index of the current cabinet within
2352 * that set. Return zero, or -1 to abort.
2354 * fdintPARTIAL_FILE:
2356 * This notification is provided when FDICopy encounters a part of a file
2357 * contained in this cabinet which is missing its beginning. Files can be
2358 * split across cabinets, so this is not necessarily an abnormality; it just
2359 * means that the file in question begins in another cabinet. No file
2360 * corresponding to this notification is extracted from the cabinet. In the
2361 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2362 * partial file, psz2 contains a pointer to the file name of the cabinet in
2363 * which this file begins, and psz3 contains a pointer to the disk name or
2364 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2366 * fdintCOPY_FILE:
2368 * This notification is provided when FDICopy encounters a file which starts
2369 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2370 * look for files in cabinets after the first one). One notification will be
2371 * sent for each such file, before the file is decompressed. By returning
2372 * zero, the callback can instruct FDICopy to skip the file. In the structure
2373 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2374 * the size of the file (uncompressed), attribs contains the file attributes,
2375 * and date and time contain the date and time of the file. attributes, date,
2376 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2377 * for the entire cabinet, 0 to skip just this file but continue scanning the
2378 * cabinet for more files, or an FDIClose()-compatible file-handle.
2380 * fdintCLOSE_FILE_INFO:
2382 * This notification is important, don't forget to implement it. This
2383 * notification indicates that a file has been successfully uncompressed and
2384 * written to disk. Upon receipt of this notification, the callee is expected
2385 * to close the file handle, to set the attributes and date/time of the
2386 * closed file, and possibly to execute the file. In the structure pointed to
2387 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2388 * open file handle (close it), cb contains 1 or zero, indicating respectively
2389 * that the callee should or should not execute the file, and date, time
2390 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2391 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2392 * do so. Return TRUE, or FALSE to abort decompression.
2394 * fdintNEXT_CABINET:
2396 * This notification is called when FDICopy must load in another cabinet. This
2397 * can occur when a file's data is "split" across multiple cabinets. The
2398 * callee has the opportunity to request that FDICopy look in a different file
2399 * path for the specified cabinet file, by writing that data into a provided
2400 * buffer (see below for more information). This notification will be received
2401 * more than once per-cabinet in the instance that FDICopy failed to find a
2402 * valid cabinet at the location specified by the first per-cabinet
2403 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2404 * structure pointed to by pfdin indicates the error which prevented FDICopy
2405 * from proceeding successfully. Return zero to indicate success, or -1 to
2406 * indicate failure and abort FDICopy.
2408 * Upon receipt of this notification, the structure pointed to by pfdin will
2409 * contain the following values: psz1 pointing to the name of the cabinet
2410 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2411 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2412 * and fdie containing either FDIERROR_NONE, or one of the following:
2414 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2415 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2416 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2417 * FDIERROR_WRONG_CABINET.
2419 * The callee may choose to change the path where FDICopy will look for the
2420 * cabinet after this notification. To do so, the caller may write the new
2421 * pathname to the buffer pointed to by psz3, which is 256 characters in
2422 * length, including the terminating null character, before returning zero.
2424 * fdintENUMERATE:
2426 * Undocumented and unimplemented in wine, this seems to be sent each time
2427 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2428 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2429 * provides information about the current cabinet instead of the next one....
2430 * this is just a guess, it has not been looked at closely.
2432 * INCLUDES
2433 * fdi.c
2435 BOOL __cdecl FDICopy(
2436 HFDI hfdi,
2437 char *pszCabinet,
2438 char *pszCabPath,
2439 int flags,
2440 PFNFDINOTIFY pfnfdin,
2441 PFNFDIDECRYPT pfnfdid,
2442 void *pvUser)
2444 FDICABINETINFO fdici;
2445 FDINOTIFICATION fdin;
2446 int cabhf, filehf, idx;
2447 unsigned int i;
2448 char fullpath[MAX_PATH];
2449 size_t pathlen, filenamelen;
2450 char emptystring = '\0';
2451 cab_UBYTE buf[64];
2452 struct fdi_folder *fol = NULL, *linkfol = NULL;
2453 struct fdi_file *file = NULL, *linkfile = NULL;
2454 fdi_decomp_state _decomp_state;
2455 fdi_decomp_state *decomp_state = &_decomp_state;
2457 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, \
2458 pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2459 hfdi, pszCabinet, pszCabPath, flags, pfnfdin, pfnfdid, pvUser);
2461 if (!REALLY_IS_FDI(hfdi)) {
2462 SetLastError(ERROR_INVALID_HANDLE);
2463 return FALSE;
2466 ZeroMemory(decomp_state, sizeof(fdi_decomp_state));
2468 pathlen = (pszCabPath) ? strlen(pszCabPath) : 0;
2469 filenamelen = (pszCabinet) ? strlen(pszCabinet) : 0;
2471 /* slight overestimation here to save CPU cycles in the developer's brain */
2472 if ((pathlen + filenamelen + 3) > MAX_PATH) {
2473 ERR("MAX_PATH exceeded.\n");
2474 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2475 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2476 PFDI_INT(hfdi)->perf->fError = TRUE;
2477 SetLastError(ERROR_FILE_NOT_FOUND);
2478 return FALSE;
2481 /* paste the path and filename together */
2482 idx = 0;
2483 if (pathlen) {
2484 for (i = 0; i < pathlen; i++) fullpath[idx++] = pszCabPath[i];
2485 if (fullpath[idx - 1] != '\\') fullpath[idx++] = '\\';
2487 if (filenamelen) for (i = 0; i < filenamelen; i++) fullpath[idx++] = pszCabinet[i];
2488 fullpath[idx] = '\0';
2490 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath));
2492 /* get a handle to the cabfile */
2493 cabhf = PFDI_OPEN(hfdi, fullpath, 32768, _S_IREAD | _S_IWRITE);
2494 if (cabhf == -1) {
2495 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2496 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2497 PFDI_INT(hfdi)->perf->fError = TRUE;
2498 SetLastError(ERROR_FILE_NOT_FOUND);
2499 return FALSE;
2502 if (cabhf == 0) {
2503 ERR("PFDI_OPEN returned zero for %s.\n", fullpath);
2504 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CABINET_NOT_FOUND;
2505 PFDI_INT(hfdi)->perf->erfType = ERROR_FILE_NOT_FOUND;
2506 PFDI_INT(hfdi)->perf->fError = TRUE;
2507 SetLastError(ERROR_FILE_NOT_FOUND);
2508 return FALSE;
2511 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2512 if (!FDI_read_entries(hfdi, cabhf, &fdici, &(CAB(mii)))) {
2513 ERR("FDIIsCabinet failed.\n");
2514 PFDI_CLOSE(hfdi, cabhf);
2515 return FALSE;
2518 /* cabinet notification */
2519 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2520 fdin.setID = fdici.setID;
2521 fdin.iCabinet = fdici.iCabinet;
2522 fdin.pv = pvUser;
2523 fdin.psz1 = (CAB(mii).nextname) ? CAB(mii).nextname : &emptystring;
2524 fdin.psz2 = (CAB(mii).nextinfo) ? CAB(mii).nextinfo : &emptystring;
2525 fdin.psz3 = pszCabPath;
2527 if (((*pfnfdin)(fdintCABINET_INFO, &fdin))) {
2528 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2529 PFDI_INT(hfdi)->perf->erfType = 0;
2530 PFDI_INT(hfdi)->perf->fError = TRUE;
2531 goto bail_and_fail;
2534 CAB(setID) = fdici.setID;
2535 CAB(iCabinet) = fdici.iCabinet;
2536 CAB(cabhf) = cabhf;
2538 /* read folders */
2539 for (i = 0; i < fdici.cFolders; i++) {
2540 if (PFDI_READ(hfdi, cabhf, buf, cffold_SIZEOF) != cffold_SIZEOF) {
2541 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2542 PFDI_INT(hfdi)->perf->erfType = 0;
2543 PFDI_INT(hfdi)->perf->fError = TRUE;
2544 goto bail_and_fail;
2547 if (CAB(mii).folder_resv > 0)
2548 PFDI_SEEK(hfdi, cabhf, CAB(mii).folder_resv, SEEK_CUR);
2550 fol = (struct fdi_folder *) PFDI_ALLOC(hfdi, sizeof(struct fdi_folder));
2551 if (!fol) {
2552 ERR("out of memory!\n");
2553 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2554 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2555 PFDI_INT(hfdi)->perf->fError = TRUE;
2556 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2557 goto bail_and_fail;
2559 ZeroMemory(fol, sizeof(struct fdi_folder));
2560 if (!CAB(firstfol)) CAB(firstfol) = fol;
2562 fol->offset = (cab_off_t) EndGetI32(buf+cffold_DataOffset);
2563 fol->num_blocks = EndGetI16(buf+cffold_NumBlocks);
2564 fol->comp_type = EndGetI16(buf+cffold_CompType);
2566 if (linkfol)
2567 linkfol->next = fol;
2568 linkfol = fol;
2571 /* read files */
2572 for (i = 0; i < fdici.cFiles; i++) {
2573 if (PFDI_READ(hfdi, cabhf, buf, cffile_SIZEOF) != cffile_SIZEOF) {
2574 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2575 PFDI_INT(hfdi)->perf->erfType = 0;
2576 PFDI_INT(hfdi)->perf->fError = TRUE;
2577 goto bail_and_fail;
2580 file = (struct fdi_file *) PFDI_ALLOC(hfdi, sizeof(struct fdi_file));
2581 if (!file) {
2582 ERR("out of memory!\n");
2583 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2584 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2585 PFDI_INT(hfdi)->perf->fError = TRUE;
2586 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2587 goto bail_and_fail;
2589 ZeroMemory(file, sizeof(struct fdi_file));
2590 if (!CAB(firstfile)) CAB(firstfile) = file;
2592 file->length = EndGetI32(buf+cffile_UncompressedSize);
2593 file->offset = EndGetI32(buf+cffile_FolderOffset);
2594 file->index = EndGetI16(buf+cffile_FolderIndex);
2595 file->time = EndGetI16(buf+cffile_Time);
2596 file->date = EndGetI16(buf+cffile_Date);
2597 file->attribs = EndGetI16(buf+cffile_Attribs);
2598 file->filename = FDI_read_string(hfdi, cabhf, fdici.cbCabinet);
2600 if (!file->filename) {
2601 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2602 PFDI_INT(hfdi)->perf->erfType = 0;
2603 PFDI_INT(hfdi)->perf->fError = TRUE;
2604 goto bail_and_fail;
2607 if (linkfile)
2608 linkfile->next = file;
2609 linkfile = file;
2612 for (file = CAB(firstfile); (file); file = file->next) {
2615 * FIXME: This implementation keeps multiple cabinet files open at once
2616 * when encountering a split cabinet. It is a quirk of this implementation
2617 * that sometimes we decrypt the same block of data more than once, to find
2618 * the right starting point for a file, moving the file-pointer backwards.
2619 * If we kept a cache of certain file-pointer information, we could eliminate
2620 * that behavior... in fact I am not sure that the caching we already have
2621 * is not sufficient.
2623 * The current implementation seems to work fine in straightforward situations
2624 * where all the cabinet files needed for decryption are simultaneously
2625 * available. But presumably, the API is supposed to support cabinets which
2626 * are split across multiple CDROMS; we may need to change our implementation
2627 * to strictly serialize it's file usage so that it opens only one cabinet
2628 * at a time. Some experimentation with Windows is needed to figure out the
2629 * precise semantics required. The relevant code is here and in fdi_decomp().
2632 /* partial-file notification */
2633 if ((file->index & cffileCONTINUED_FROM_PREV) == cffileCONTINUED_FROM_PREV) {
2635 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2636 * and perform some tests to figure out the right behavior. The SDK says
2637 * FDICopy will notify the user of the filename and "disk name" (info) of
2638 * the cabinet where the spanning file /started/.
2640 * That would certainly be convenient for the API-user, who could abort,
2641 * everything (or parallelize, if that's allowed (it is in wine)), and call
2642 * FDICopy again with the provided filename, so as to avoid partial file
2643 * notification and successfully unpack. This task could be quite unpleasant
2644 * from wine's perspective: the information specifying the "start cabinet" for
2645 * a file is associated nowhere with the file header and is not to be found in
2646 * the cabinet header. We have only the index of the cabinet wherein the folder
2647 * begins, which contains the file. To find that cabinet, we must consider the
2648 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2649 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2650 * list).
2652 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2653 * cabinet other than the active one might be at another filepath than the
2654 * current one, or on another CDROM. This could get rather dicey, especially
2655 * if we imagine parallelized access to the FDICopy API.
2657 * The current implementation punts -- it just returns the previous cabinet and
2658 * it's info from the header of this cabinet. This provides the right answer in
2659 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2660 * we "fix" it.
2662 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2663 fdin.pv = pvUser;
2664 fdin.psz1 = (char *)file->filename;
2665 fdin.psz2 = (CAB(mii).prevname) ? CAB(mii).prevname : &emptystring;
2666 fdin.psz3 = (CAB(mii).previnfo) ? CAB(mii).previnfo : &emptystring;
2668 if (((*pfnfdin)(fdintPARTIAL_FILE, &fdin))) {
2669 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2670 PFDI_INT(hfdi)->perf->erfType = 0;
2671 PFDI_INT(hfdi)->perf->fError = TRUE;
2672 goto bail_and_fail;
2674 /* I don't think we are supposed to decompress partial files. This prevents it. */
2675 file->oppressed = TRUE;
2677 if (file->oppressed) {
2678 filehf = 0;
2679 } else {
2680 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2681 fdin.pv = pvUser;
2682 fdin.psz1 = (char *)file->filename;
2683 fdin.cb = file->length;
2684 fdin.date = file->date;
2685 fdin.time = file->time;
2686 fdin.attribs = file->attribs;
2687 if ((filehf = ((*pfnfdin)(fdintCOPY_FILE, &fdin))) == -1) {
2688 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2689 PFDI_INT(hfdi)->perf->erfType = 0;
2690 PFDI_INT(hfdi)->perf->fError = TRUE;
2691 goto bail_and_fail;
2695 /* find the folder for this file if necc. */
2696 if (filehf) {
2697 int i2;
2699 fol = CAB(firstfol);
2700 if ((file->index & cffileCONTINUED_TO_NEXT) == cffileCONTINUED_TO_NEXT) {
2701 /* pick the last folder */
2702 while (fol->next) fol = fol->next;
2703 } else {
2704 for (i2 = 0; (i2 < file->index); i2++)
2705 if (fol->next) /* bug resistance, should always be true */
2706 fol = fol->next;
2710 if (filehf) {
2711 cab_UWORD comptype = fol->comp_type;
2712 int ct1 = comptype & cffoldCOMPTYPE_MASK;
2713 int ct2 = CAB(current) ? (CAB(current)->comp_type & cffoldCOMPTYPE_MASK) : 0;
2714 int err = 0;
2716 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file->filename));
2718 /* set up decomp_state */
2719 CAB(hfdi) = hfdi;
2720 CAB(filehf) = filehf;
2722 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2723 if ((ct1 != ct2) || (CAB(current) != fol) || (file->offset < CAB(offset))) {
2725 TRACE("Resetting folder for file %s.\n", debugstr_a(file->filename));
2727 /* free stuff for the old decompresser */
2728 switch (ct2) {
2729 case cffoldCOMPTYPE_LZX:
2730 if (LZX(window)) {
2731 PFDI_FREE(hfdi, LZX(window));
2732 LZX(window) = NULL;
2734 break;
2735 case cffoldCOMPTYPE_QUANTUM:
2736 if (QTM(window)) {
2737 PFDI_FREE(hfdi, QTM(window));
2738 QTM(window) = NULL;
2740 break;
2743 CAB(decomp_cab) = NULL;
2744 PFDI_SEEK(CAB(hfdi), CAB(cabhf), fol->offset, SEEK_SET);
2745 CAB(offset) = 0;
2746 CAB(outlen) = 0;
2748 /* initialize the new decompresser */
2749 switch (ct1) {
2750 case cffoldCOMPTYPE_NONE:
2751 CAB(decompress) = NONEfdi_decomp;
2752 break;
2753 case cffoldCOMPTYPE_MSZIP:
2754 CAB(decompress) = ZIPfdi_decomp;
2755 break;
2756 case cffoldCOMPTYPE_QUANTUM:
2757 CAB(decompress) = QTMfdi_decomp;
2758 err = QTMfdi_init((comptype >> 8) & 0x1f, (comptype >> 4) & 0xF, decomp_state);
2759 break;
2760 case cffoldCOMPTYPE_LZX:
2761 CAB(decompress) = LZXfdi_decomp;
2762 err = LZXfdi_init((comptype >> 8) & 0x1f, decomp_state);
2763 break;
2764 default:
2765 err = DECR_DATAFORMAT;
2769 CAB(current) = fol;
2771 switch (err) {
2772 case DECR_OK:
2773 break;
2774 case DECR_NOMEMORY:
2775 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2776 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2777 PFDI_INT(hfdi)->perf->fError = TRUE;
2778 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2779 goto bail_and_fail;
2780 default:
2781 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2782 PFDI_INT(hfdi)->perf->erfOper = 0;
2783 PFDI_INT(hfdi)->perf->fError = TRUE;
2784 goto bail_and_fail;
2787 if (file->offset > CAB(offset)) {
2788 /* decode bytes and send them to /dev/null */
2789 switch ((err = fdi_decomp(file, 0, decomp_state, pszCabPath, pfnfdin, pvUser))) {
2790 case DECR_OK:
2791 break;
2792 case DECR_USERABORT:
2793 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2794 PFDI_INT(hfdi)->perf->erfType = 0;
2795 PFDI_INT(hfdi)->perf->fError = TRUE;
2796 goto bail_and_fail;
2797 case DECR_NOMEMORY:
2798 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2799 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2800 PFDI_INT(hfdi)->perf->fError = TRUE;
2801 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2802 goto bail_and_fail;
2803 default:
2804 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2805 PFDI_INT(hfdi)->perf->erfOper = 0;
2806 PFDI_INT(hfdi)->perf->fError = TRUE;
2807 goto bail_and_fail;
2809 CAB(offset) = file->offset;
2812 /* now do the actual decompression */
2813 err = fdi_decomp(file, 1, decomp_state, pszCabPath, pfnfdin, pvUser);
2814 if (err) CAB(current) = NULL; else CAB(offset) += file->length;
2816 switch (err) {
2817 case DECR_OK:
2818 break;
2819 case DECR_USERABORT:
2820 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2821 PFDI_INT(hfdi)->perf->erfType = 0;
2822 PFDI_INT(hfdi)->perf->fError = TRUE;
2823 goto bail_and_fail;
2824 case DECR_NOMEMORY:
2825 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_ALLOC_FAIL;
2826 PFDI_INT(hfdi)->perf->erfType = ERROR_NOT_ENOUGH_MEMORY;
2827 PFDI_INT(hfdi)->perf->fError = TRUE;
2828 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2829 goto bail_and_fail;
2830 default:
2831 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_CORRUPT_CABINET;
2832 PFDI_INT(hfdi)->perf->erfOper = 0;
2833 PFDI_INT(hfdi)->perf->fError = TRUE;
2834 goto bail_and_fail;
2837 /* fdintCLOSE_FILE_INFO notification */
2838 ZeroMemory(&fdin, sizeof(FDINOTIFICATION));
2839 fdin.pv = pvUser;
2840 fdin.psz1 = (char *)file->filename;
2841 fdin.hf = filehf;
2842 fdin.cb = (file->attribs & cffile_A_EXEC) ? TRUE : FALSE; /* FIXME: is that right? */
2843 fdin.date = file->date;
2844 fdin.time = file->time;
2845 fdin.attribs = file->attribs; /* FIXME: filter _A_EXEC? */
2846 err = ((*pfnfdin)(fdintCLOSE_FILE_INFO, &fdin));
2847 if (err == FALSE || err == -1) {
2849 * SDK states that even though they indicated failure,
2850 * we are not supposed to try and close the file, so we
2851 * just treat this like all the others
2853 PFDI_INT(hfdi)->perf->erfOper = FDIERROR_USER_ABORT;
2854 PFDI_INT(hfdi)->perf->erfType = 0;
2855 PFDI_INT(hfdi)->perf->fError = TRUE;
2856 goto bail_and_fail;
2861 /* free decompression temps */
2862 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2863 case cffoldCOMPTYPE_LZX:
2864 if (LZX(window)) {
2865 PFDI_FREE(hfdi, LZX(window));
2866 LZX(window) = NULL;
2868 break;
2869 case cffoldCOMPTYPE_QUANTUM:
2870 if (QTM(window)) {
2871 PFDI_FREE(hfdi, QTM(window));
2872 QTM(window) = NULL;
2874 break;
2877 while (decomp_state) {
2878 fdi_decomp_state *prev_fds;
2880 PFDI_CLOSE(hfdi, CAB(cabhf));
2882 /* free the storage remembered by mii */
2883 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2884 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2885 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2886 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2888 while (CAB(firstfol)) {
2889 fol = CAB(firstfol);
2890 CAB(firstfol) = CAB(firstfol)->next;
2891 PFDI_FREE(hfdi, fol);
2893 while (CAB(firstfile)) {
2894 file = CAB(firstfile);
2895 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2896 CAB(firstfile) = CAB(firstfile)->next;
2897 PFDI_FREE(hfdi, file);
2899 prev_fds = decomp_state;
2900 decomp_state = CAB(next);
2901 if (prev_fds != &_decomp_state)
2902 PFDI_FREE(hfdi, prev_fds);
2905 return TRUE;
2907 bail_and_fail: /* here we free ram before error returns */
2909 /* free decompression temps */
2910 switch (fol->comp_type & cffoldCOMPTYPE_MASK) {
2911 case cffoldCOMPTYPE_LZX:
2912 if (LZX(window)) {
2913 PFDI_FREE(hfdi, LZX(window));
2914 LZX(window) = NULL;
2916 break;
2917 case cffoldCOMPTYPE_QUANTUM:
2918 if (QTM(window)) {
2919 PFDI_FREE(hfdi, QTM(window));
2920 QTM(window) = NULL;
2922 break;
2925 while (decomp_state) {
2926 fdi_decomp_state *prev_fds;
2928 PFDI_CLOSE(hfdi, CAB(cabhf));
2930 /* free the storage remembered by mii */
2931 if (CAB(mii).nextname) PFDI_FREE(hfdi, CAB(mii).nextname);
2932 if (CAB(mii).nextinfo) PFDI_FREE(hfdi, CAB(mii).nextinfo);
2933 if (CAB(mii).prevname) PFDI_FREE(hfdi, CAB(mii).prevname);
2934 if (CAB(mii).previnfo) PFDI_FREE(hfdi, CAB(mii).previnfo);
2936 while (CAB(firstfol)) {
2937 fol = CAB(firstfol);
2938 CAB(firstfol) = CAB(firstfol)->next;
2939 PFDI_FREE(hfdi, fol);
2941 while (CAB(firstfile)) {
2942 file = CAB(firstfile);
2943 if (file->filename) PFDI_FREE(hfdi, (void *)file->filename);
2944 CAB(firstfile) = CAB(firstfile)->next;
2945 PFDI_FREE(hfdi, file);
2947 prev_fds = decomp_state;
2948 decomp_state = CAB(next);
2949 if (prev_fds != &_decomp_state)
2950 PFDI_FREE(hfdi, prev_fds);
2953 return FALSE;
2956 /***********************************************************************
2957 * FDIDestroy (CABINET.23)
2959 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2960 * of FDICopy. Only reason for failure would be an invalid handle.
2962 * PARAMS
2963 * hfdi [I] The HFDI to free
2965 * RETURNS
2966 * TRUE for success
2967 * FALSE for failure
2969 BOOL __cdecl FDIDestroy(HFDI hfdi)
2971 TRACE("(hfdi == ^%p)\n", hfdi);
2972 if (REALLY_IS_FDI(hfdi)) {
2973 PFDI_INT(hfdi)->FDI_Intmagic = 0; /* paranoia */
2974 PFDI_FREE(hfdi, hfdi); /* confusing, but correct */
2975 return TRUE;
2976 } else {
2977 SetLastError(ERROR_INVALID_HANDLE);
2978 return FALSE;
2982 /***********************************************************************
2983 * FDITruncateCabinet (CABINET.24)
2985 * Removes all folders of a cabinet file after and including the
2986 * specified folder number.
2988 * PARAMS
2989 * hfdi [I] Handle to the FDI context.
2990 * pszCabinetName [I] Filename of the cabinet.
2991 * iFolderToDelete [I] Index of the first folder to delete.
2993 * RETURNS
2994 * Success: TRUE.
2995 * Failure: FALSE.
2997 * NOTES
2998 * The PFNWRITE function supplied to FDICreate must truncate the
2999 * file at the current position if the number of bytes to write is 0.
3001 BOOL __cdecl FDITruncateCabinet(
3002 HFDI hfdi,
3003 char *pszCabinetName,
3004 USHORT iFolderToDelete)
3006 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
3007 hfdi, debugstr_a(pszCabinetName), iFolderToDelete);
3009 if (!REALLY_IS_FDI(hfdi)) {
3010 SetLastError(ERROR_INVALID_HANDLE);
3011 return FALSE;
3014 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3015 return FALSE;