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
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?
46 * Probably, I need to weed out some dead code-paths.
50 * The fdintNEXT_CABINET callbacks are probably not working quite as they should.
51 * There are several FIXMEs 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.
68 struct fdi_file
*next
; /* next file in sequence */
69 LPSTR filename
; /* output name of file */
70 int fh
; /* open file handle or NULL */
71 cab_ULONG length
; /* uncompressed length of file */
72 cab_ULONG offset
; /* uncompressed offset in folder */
73 cab_UWORD index
; /* magic index number of folder */
74 cab_UWORD time
, date
, attribs
; /* MS-DOS time/date/attributes */
75 BOOL oppressed
; /* never to be processed */
79 struct fdi_folder
*next
;
80 cab_off_t offset
; /* offset to data blocks (32 bit) */
81 cab_UWORD comp_type
; /* compression format/window size */
82 cab_ULONG comp_size
; /* compressed size of folder */
83 cab_UBYTE num_splits
; /* number of split blocks + 1 */
84 cab_UWORD num_blocks
; /* total number of blocks */
88 * this structure fills the gaps between what is available in a PFDICABINETINFO
89 * vs what is needed by FDICopy. Memory allocated for these becomes the responsibility
90 * of the caller to free. Yes, I am aware that this is totally, utterly inelegant.
91 * To make things even more unnecessarily confusing, we now attach these to the
95 char *prevname
, *previnfo
;
96 char *nextname
, *nextinfo
;
97 BOOL hasnext
; /* bug free indicator */
98 int folder_resv
, header_resv
;
100 } MORE_ISCAB_INFO
, *PMORE_ISCAB_INFO
;
115 #define FDI_INT_MAGIC 0xfdfdfd05
118 * ugh, well, this ended up being pretty damn silly...
119 * now that I've conceded to build equivalent structures to struct cab.*,
120 * I should have just used those, or, better yet, unified the two... sue me.
121 * (Note to Microsoft: That's a joke. Please /don't/ actually sue me! -gmt).
122 * Nevertheless, I've come this far, it works, so I'm not gonna change it
123 * for now. This implementation has significant semantic differences anyhow.
126 typedef struct fdi_cds_fwd
{
127 FDI_Int
*fdi
; /* the hfdi we are using */
128 INT_PTR filehf
, cabhf
; /* file handle we are using */
129 struct fdi_folder
*current
; /* current folder we're extracting from */
130 cab_ULONG offset
; /* uncompressed offset within folder */
131 cab_UBYTE
*outpos
; /* (high level) start of data to use up */
132 cab_UWORD outlen
; /* (high level) amount of data to use up */
133 int (*decompress
)(int, int, struct fdi_cds_fwd
*); /* chosen compress fn */
134 cab_UBYTE inbuf
[CAB_INPUTMAX
+2]; /* +2 for lzx bitbuffer overflows! */
135 cab_UBYTE outbuf
[CAB_BLOCKMAX
];
141 /* some temp variables for use during decompression */
142 cab_UBYTE q_length_base
[27], q_length_extra
[27], q_extra_bits
[42];
143 cab_ULONG q_position_base
[42];
144 cab_ULONG lzx_position_base
[51];
145 cab_UBYTE extra_bits
[51];
146 USHORT setID
; /* Cabinet set ID */
147 USHORT iCabinet
; /* Cabinet number in set (0 based) */
148 struct fdi_cds_fwd
*decomp_cab
;
150 struct fdi_folder
*firstfol
;
151 struct fdi_file
*firstfile
;
152 struct fdi_cds_fwd
*next
;
155 #define ZIPNEEDBITS(n) {while(k<(n)){cab_LONG c=*(ZIP(inpos)++);\
156 b|=((cab_ULONG)c)<<k;k+=8;}}
157 #define ZIPDUMPBITS(n) {b>>=(n);k-=(n);}
159 /* endian-neutral reading of little-endian data */
160 #define EndGetI32(a) ((((a)[3])<<24)|(((a)[2])<<16)|(((a)[1])<<8)|((a)[0]))
161 #define EndGetI16(a) ((((a)[1])<<8)|((a)[0]))
163 #define CAB(x) (decomp_state->x)
164 #define ZIP(x) (decomp_state->methods.zip.x)
165 #define QTM(x) (decomp_state->methods.qtm.x)
166 #define LZX(x) (decomp_state->methods.lzx.x)
168 #define DECR_DATAFORMAT (1)
169 #define DECR_ILLEGALDATA (2)
170 #define DECR_NOMEMORY (3)
171 #define DECR_CHECKSUM (4)
172 #define DECR_INPUT (5)
173 #define DECR_OUTPUT (6)
174 #define DECR_USERABORT (7)
176 static void set_error( FDI_Int
*fdi
, int oper
, int err
)
178 fdi
->perf
->erfOper
= oper
;
179 fdi
->perf
->erfType
= err
;
180 fdi
->perf
->fError
= TRUE
;
181 if (err
) SetLastError( err
);
184 static FDI_Int
*get_fdi_ptr( HFDI hfdi
)
186 FDI_Int
*fdi
= (FDI_Int
*)hfdi
;
188 if (!fdi
|| fdi
->magic
!= FDI_INT_MAGIC
)
190 SetLastError( ERROR_INVALID_HANDLE
);
196 /****************************************************************
197 * QTMupdatemodel (internal)
199 static void QTMupdatemodel(struct QTMmodel
*model
, int sym
) {
200 struct QTMmodelsym temp
;
203 for (i
= 0; i
< sym
; i
++) model
->syms
[i
].cumfreq
+= 8;
205 if (model
->syms
[0].cumfreq
> 3800) {
206 if (--model
->shiftsleft
) {
207 for (i
= model
->entries
- 1; i
>= 0; i
--) {
208 /* -1, not -2; the 0 entry saves this */
209 model
->syms
[i
].cumfreq
>>= 1;
210 if (model
->syms
[i
].cumfreq
<= model
->syms
[i
+1].cumfreq
) {
211 model
->syms
[i
].cumfreq
= model
->syms
[i
+1].cumfreq
+ 1;
216 model
->shiftsleft
= 50;
217 for (i
= 0; i
< model
->entries
; i
++) {
218 /* no -1, want to include the 0 entry */
219 /* this converts cumfreqs into frequencies, then shifts right */
220 model
->syms
[i
].cumfreq
-= model
->syms
[i
+1].cumfreq
;
221 model
->syms
[i
].cumfreq
++; /* avoid losing things entirely */
222 model
->syms
[i
].cumfreq
>>= 1;
225 /* now sort by frequencies, decreasing order -- this must be an
226 * inplace selection sort, or a sort with the same (in)stability
229 for (i
= 0; i
< model
->entries
- 1; i
++) {
230 for (j
= i
+ 1; j
< model
->entries
; j
++) {
231 if (model
->syms
[i
].cumfreq
< model
->syms
[j
].cumfreq
) {
232 temp
= model
->syms
[i
];
233 model
->syms
[i
] = model
->syms
[j
];
234 model
->syms
[j
] = temp
;
239 /* then convert frequencies back to cumfreq */
240 for (i
= model
->entries
- 1; i
>= 0; i
--) {
241 model
->syms
[i
].cumfreq
+= model
->syms
[i
+1].cumfreq
;
243 /* then update the other part of the table */
244 for (i
= 0; i
< model
->entries
; i
++) {
245 model
->tabloc
[model
->syms
[i
].sym
] = i
;
251 /*************************************************************************
252 * make_decode_table (internal)
254 * This function was coded by David Tritscher. It builds a fast huffman
255 * decoding table out of just a canonical huffman code lengths table.
258 * nsyms: total number of symbols in this huffman tree.
259 * nbits: any symbols with a code length of nbits or less can be decoded
260 * in one lookup of the table.
261 * length: A table to get code lengths from [0 to syms-1]
262 * table: The table to fill up with decoded symbols and pointers.
268 static int make_decode_table(cab_ULONG nsyms
, cab_ULONG nbits
,
269 const cab_UBYTE
*length
, cab_UWORD
*table
) {
270 register cab_UWORD sym
;
271 register cab_ULONG leaf
;
272 register cab_UBYTE bit_num
= 1;
274 cab_ULONG pos
= 0; /* the current position in the decode table */
275 cab_ULONG table_mask
= 1 << nbits
;
276 cab_ULONG bit_mask
= table_mask
>> 1; /* don't do 0 length codes */
277 cab_ULONG next_symbol
= bit_mask
; /* base of allocation for long codes */
279 /* fill entries for codes short enough for a direct mapping */
280 while (bit_num
<= nbits
) {
281 for (sym
= 0; sym
< nsyms
; sym
++) {
282 if (length
[sym
] == bit_num
) {
285 if((pos
+= bit_mask
) > table_mask
) return 1; /* table overrun */
287 /* fill all possible lookups of this symbol with the symbol itself */
289 while (fill
-- > 0) table
[leaf
++] = sym
;
296 /* if there are any codes longer than nbits */
297 if (pos
!= table_mask
) {
298 /* clear the remainder of the table */
299 for (sym
= pos
; sym
< table_mask
; sym
++) table
[sym
] = 0;
301 /* give ourselves room for codes to grow by up to 16 more bits */
306 while (bit_num
<= 16) {
307 for (sym
= 0; sym
< nsyms
; sym
++) {
308 if (length
[sym
] == bit_num
) {
310 for (fill
= 0; fill
< bit_num
- nbits
; fill
++) {
311 /* if this path hasn't been taken yet, 'allocate' two entries */
312 if (table
[leaf
] == 0) {
313 table
[(next_symbol
<< 1)] = 0;
314 table
[(next_symbol
<< 1) + 1] = 0;
315 table
[leaf
] = next_symbol
++;
317 /* follow the path and select either left or right for next bit */
318 leaf
= table
[leaf
] << 1;
319 if ((pos
>> (15-fill
)) & 1) leaf
++;
323 if ((pos
+= bit_mask
) > table_mask
) return 1; /* table overflow */
332 if (pos
== table_mask
) return 0;
334 /* either erroneous table, or all elements are 0 - let's find out. */
335 for (sym
= 0; sym
< nsyms
; sym
++) if (length
[sym
]) return 1;
339 /*************************************************************************
340 * checksum (internal)
342 static cab_ULONG
checksum(const cab_UBYTE
*data
, cab_UWORD bytes
, cab_ULONG csum
) {
346 for (len
= bytes
>> 2; len
--; data
+= 4) {
347 csum
^= ((data
[0]) | (data
[1]<<8) | (data
[2]<<16) | (data
[3]<<24));
351 case 3: ul
|= *data
++ << 16;
353 case 2: ul
|= *data
++ << 8;
362 /***********************************************************************
363 * FDICreate (CABINET.20)
365 * Provided with several callbacks (all of them are mandatory),
366 * returns a handle which can be used to perform operations
370 * pfnalloc [I] A pointer to a function which allocates ram. Uses
371 * the same interface as malloc.
372 * pfnfree [I] A pointer to a function which frees ram. Uses the
373 * same interface as free.
374 * pfnopen [I] A pointer to a function which opens a file. Uses
375 * the same interface as _open.
376 * pfnread [I] A pointer to a function which reads from a file into
377 * a caller-provided buffer. Uses the same interface
379 * pfnwrite [I] A pointer to a function which writes to a file from
380 * a caller-provided buffer. Uses the same interface
382 * pfnclose [I] A pointer to a function which closes a file handle.
383 * Uses the same interface as _close.
384 * pfnseek [I] A pointer to a function which seeks in a file.
385 * Uses the same interface as _lseek.
386 * cpuType [I] The type of CPU; ignored in wine (recommended value:
387 * cpuUNKNOWN, aka -1).
388 * perf [IO] A pointer to an ERF structure. When FDICreate
389 * returns an error condition, error information may
390 * be found here as well as from GetLastError.
393 * On success, returns an FDI handle of type HFDI.
394 * On failure, the NULL file handle is returned. Error
395 * info can be retrieved from perf.
401 HFDI __cdecl
FDICreate(
414 TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, "
415 "pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
416 pfnalloc
, pfnfree
, pfnopen
, pfnread
, pfnwrite
, pfnclose
, pfnseek
,
419 if ((!pfnalloc
) || (!pfnfree
)) {
420 perf
->erfOper
= FDIERROR_NONE
;
421 perf
->erfType
= ERROR_BAD_ARGUMENTS
;
424 SetLastError(ERROR_BAD_ARGUMENTS
);
428 if (!((fdi
= pfnalloc(sizeof(FDI_Int
))))) {
429 perf
->erfOper
= FDIERROR_ALLOC_FAIL
;
435 fdi
->magic
= FDI_INT_MAGIC
;
436 fdi
->alloc
= pfnalloc
;
440 fdi
->write
= pfnwrite
;
441 fdi
->close
= pfnclose
;
443 /* no-brainer: we ignore the cpu type; this is only used
444 for the 16-bit versions in Windows anyhow... */
450 /*******************************************************************
451 * FDI_getoffset (internal)
453 * returns the file pointer position of a file handle.
455 static LONG
FDI_getoffset(FDI_Int
*fdi
, INT_PTR hf
)
457 return fdi
->seek(hf
, 0, SEEK_CUR
);
460 /**********************************************************************
461 * FDI_read_string (internal)
463 * allocate and read an arbitrarily long string from the cabinet
465 static char *FDI_read_string(FDI_Int
*fdi
, INT_PTR hf
, long cabsize
)
468 base
= FDI_getoffset(fdi
, hf
),
469 maxlen
= cabsize
- base
;
472 cab_UBYTE
*buf
= NULL
;
474 TRACE("(fdi == %p, hf == %ld, cabsize == %ld)\n", fdi
, hf
, cabsize
);
477 if (len
> maxlen
) len
= maxlen
;
478 if (!(buf
= fdi
->alloc(len
))) break;
479 if (!fdi
->read(hf
, buf
, len
)) break;
481 /* search for a null terminator in what we've just read */
482 for (i
=0; i
< len
; i
++) {
483 if (!buf
[i
]) {ok
=TRUE
; break;}
488 ERR("cabinet is truncated\n");
491 /* The buffer is too small for the string. Reset the file to the point
492 * were we started, free the buffer and increase the size for the next try
494 fdi
->seek(hf
, base
, SEEK_SET
);
505 ERR("out of memory!\n");
509 /* otherwise, set the stream to just after the string and return */
510 fdi
->seek(hf
, base
+ strlen((char *)buf
) + 1, SEEK_SET
);
515 /******************************************************************
516 * FDI_read_entries (internal)
518 * process the cabinet header in the style of FDIIsCabinet, but
519 * without the sanity checks (and bug)
521 static BOOL
FDI_read_entries(
524 PFDICABINETINFO pfdici
,
525 PMORE_ISCAB_INFO pmii
)
527 int num_folders
, num_files
, header_resv
, folder_resv
= 0;
529 USHORT setid
, cabidx
, flags
;
530 cab_UBYTE buf
[64], block_resv
;
531 char *prevname
= NULL
, *previnfo
= NULL
, *nextname
= NULL
, *nextinfo
= NULL
;
533 TRACE("(fdi == ^%p, hf == %ld, pfdici == ^%p)\n", fdi
, hf
, pfdici
);
535 /* read in the CFHEADER */
536 if (fdi
->read(hf
, buf
, cfhead_SIZEOF
) != cfhead_SIZEOF
) {
537 if (pmii
) set_error( fdi
, FDIERROR_NOT_A_CABINET
, 0 );
541 /* check basic MSCF signature */
542 if (EndGetI32(buf
+cfhead_Signature
) != 0x4643534d) {
543 if (pmii
) set_error( fdi
, FDIERROR_NOT_A_CABINET
, 0 );
547 /* get the cabinet size */
548 cabsize
= EndGetI32(buf
+cfhead_CabinetSize
);
550 /* get the number of folders */
551 num_folders
= EndGetI16(buf
+cfhead_NumFolders
);
553 /* get the number of files */
554 num_files
= EndGetI16(buf
+cfhead_NumFiles
);
557 setid
= EndGetI16(buf
+cfhead_SetID
);
559 /* cabinet (set) index */
560 cabidx
= EndGetI16(buf
+cfhead_CabinetIndex
);
562 /* check the header revision */
563 if ((buf
[cfhead_MajorVersion
] > 1) ||
564 (buf
[cfhead_MajorVersion
] == 1 && buf
[cfhead_MinorVersion
] > 3))
566 WARN("cabinet format version > 1.3\n");
567 if (pmii
) set_error( fdi
, FDIERROR_UNKNOWN_CABINET_VERSION
, 0 /* ? */ );
571 /* pull the flags out */
572 flags
= EndGetI16(buf
+cfhead_Flags
);
574 /* read the reserved-sizes part of header, if present */
575 if (flags
& cfheadRESERVE_PRESENT
) {
576 if (fdi
->read(hf
, buf
, cfheadext_SIZEOF
) != cfheadext_SIZEOF
) {
577 ERR("bunk reserve-sizes?\n");
578 if (pmii
) set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 /* ? */ );
582 header_resv
= EndGetI16(buf
+cfheadext_HeaderReserved
);
583 if (pmii
) pmii
->header_resv
= header_resv
;
584 folder_resv
= buf
[cfheadext_FolderReserved
];
585 if (pmii
) pmii
->folder_resv
= folder_resv
;
586 block_resv
= buf
[cfheadext_DataReserved
];
587 if (pmii
) pmii
->block_resv
= block_resv
;
589 if (header_resv
> 60000) {
590 WARN("WARNING; header reserved space > 60000\n");
593 /* skip the reserved header */
594 if ((header_resv
) && (fdi
->seek(hf
, header_resv
, SEEK_CUR
) == -1)) {
595 ERR("seek failure: header_resv\n");
596 if (pmii
) set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 /* ? */ );
601 if (flags
& cfheadPREV_CABINET
) {
602 prevname
= FDI_read_string(fdi
, hf
, cabsize
);
604 if (pmii
) set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 /* ? */ );
608 pmii
->prevname
= prevname
;
611 previnfo
= FDI_read_string(fdi
, hf
, cabsize
);
614 pmii
->previnfo
= previnfo
;
620 if (flags
& cfheadNEXT_CABINET
) {
622 pmii
->hasnext
= TRUE
;
623 nextname
= FDI_read_string(fdi
, hf
, cabsize
);
625 if ((flags
& cfheadPREV_CABINET
) && pmii
) {
626 if (pmii
->prevname
) fdi
->free(prevname
);
627 if (pmii
->previnfo
) fdi
->free(previnfo
);
629 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 /* ? */ );
633 pmii
->nextname
= nextname
;
636 nextinfo
= FDI_read_string(fdi
, hf
, cabsize
);
639 pmii
->nextinfo
= nextinfo
;
645 /* we could process the whole cabinet searching for problems;
646 instead lets stop here. Now let's fill out the paperwork */
647 pfdici
->cbCabinet
= cabsize
;
648 pfdici
->cFolders
= num_folders
;
649 pfdici
->cFiles
= num_files
;
650 pfdici
->setID
= setid
;
651 pfdici
->iCabinet
= cabidx
;
652 pfdici
->fReserve
= (flags
& cfheadRESERVE_PRESENT
) != 0;
653 pfdici
->hasprev
= (flags
& cfheadPREV_CABINET
) != 0;
654 pfdici
->hasnext
= (flags
& cfheadNEXT_CABINET
) != 0;
658 /***********************************************************************
659 * FDIIsCabinet (CABINET.21)
661 * Informs the caller as to whether or not the provided file handle is
662 * really a cabinet or not, filling out the provided PFDICABINETINFO
663 * structure with information about the cabinet. Brief explanations of
664 * the elements of this structure are available as comments accompanying
665 * its definition in wine's include/fdi.h.
668 * hfdi [I] An HFDI from FDICreate
669 * hf [I] The file handle about which the caller inquires
670 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
671 * be filled out with information about the cabinet
672 * file indicated by hf if, indeed, it is determined
676 * TRUE if the file is a cabinet. The info pointed to by pfdici will
678 * FALSE if the file is not a cabinet, or if an error was encountered
679 * while processing the cabinet. The PERF structure provided to
680 * FDICreate can be queried for more error information.
685 BOOL __cdecl
FDIIsCabinet(HFDI hfdi
, INT_PTR hf
, PFDICABINETINFO pfdici
)
688 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
690 TRACE("(hfdi == ^%p, hf == ^%ld, pfdici == ^%p)\n", hfdi
, hf
, pfdici
);
692 if (!fdi
) return FALSE
;
695 SetLastError(ERROR_INVALID_HANDLE
);
700 SetLastError(ERROR_BAD_ARGUMENTS
);
703 rv
= FDI_read_entries(fdi
, hf
, pfdici
, NULL
);
706 pfdici
->hasnext
= FALSE
; /* yuck. duplicate apparent cabinet.dll bug */
711 /******************************************************************
712 * QTMfdi_initmodel (internal)
714 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
716 static void QTMfdi_initmodel(struct QTMmodel
*m
, struct QTMmodelsym
*sym
, int n
, int s
) {
721 memset(m
->tabloc
, 0xFF, sizeof(m
->tabloc
)); /* clear out look-up table */
722 for (i
= 0; i
< n
; i
++) {
723 m
->tabloc
[i
+s
] = i
; /* set up a look-up entry for symbol */
724 m
->syms
[i
].sym
= i
+s
; /* actual symbol */
725 m
->syms
[i
].cumfreq
= n
-i
; /* current frequency of that symbol */
727 m
->syms
[n
].cumfreq
= 0;
730 /******************************************************************
731 * QTMfdi_init (internal)
733 static int QTMfdi_init(int window
, int level
, fdi_decomp_state
*decomp_state
) {
734 unsigned int wndsize
= 1 << window
;
735 int msz
= window
* 2, i
;
738 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
739 /* if a previously allocated window is big enough, keep it */
740 if (window
< 10 || window
> 21) return DECR_DATAFORMAT
;
741 if (QTM(actual_size
) < wndsize
) {
742 if (QTM(window
)) CAB(fdi
)->free(QTM(window
));
746 if (!(QTM(window
) = CAB(fdi
)->alloc(wndsize
))) return DECR_NOMEMORY
;
747 QTM(actual_size
) = wndsize
;
749 QTM(window_size
) = wndsize
;
750 QTM(window_posn
) = 0;
752 /* initialize static slot/extrabits tables */
753 for (i
= 0, j
= 0; i
< 27; i
++) {
754 CAB(q_length_extra
)[i
] = (i
== 26) ? 0 : (i
< 2 ? 0 : i
- 2) >> 2;
755 CAB(q_length_base
)[i
] = j
; j
+= 1 << ((i
== 26) ? 5 : CAB(q_length_extra
)[i
]);
757 for (i
= 0, j
= 0; i
< 42; i
++) {
758 CAB(q_extra_bits
)[i
] = (i
< 2 ? 0 : i
-2) >> 1;
759 CAB(q_position_base
)[i
] = j
; j
+= 1 << CAB(q_extra_bits
)[i
];
762 /* initialize arithmetic coding models */
764 QTMfdi_initmodel(&QTM(model7
), QTM(m7sym
), 7, 0);
766 QTMfdi_initmodel(&QTM(model00
), QTM(m00sym
), 0x40, 0x00);
767 QTMfdi_initmodel(&QTM(model40
), QTM(m40sym
), 0x40, 0x40);
768 QTMfdi_initmodel(&QTM(model80
), QTM(m80sym
), 0x40, 0x80);
769 QTMfdi_initmodel(&QTM(modelC0
), QTM(mC0sym
), 0x40, 0xC0);
771 /* model 4 depends on table size, ranges from 20 to 24 */
772 QTMfdi_initmodel(&QTM(model4
), QTM(m4sym
), (msz
< 24) ? msz
: 24, 0);
773 /* model 5 depends on table size, ranges from 20 to 36 */
774 QTMfdi_initmodel(&QTM(model5
), QTM(m5sym
), (msz
< 36) ? msz
: 36, 0);
775 /* model 6pos depends on table size, ranges from 20 to 42 */
776 QTMfdi_initmodel(&QTM(model6pos
), QTM(m6psym
), msz
, 0);
777 QTMfdi_initmodel(&QTM(model6len
), QTM(m6lsym
), 27, 0);
782 /************************************************************
783 * LZXfdi_init (internal)
785 static int LZXfdi_init(int window
, fdi_decomp_state
*decomp_state
) {
786 static const cab_UBYTE bits
[] =
787 { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
788 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
789 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
791 static const cab_ULONG base
[] =
792 { 0, 1, 2, 3, 4, 6, 8, 12,
793 16, 24, 32, 48, 64, 96, 128, 192,
794 256, 384, 512, 768, 1024, 1536, 2048, 3072,
795 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
796 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
797 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
798 1835008, 1966080, 2097152};
799 cab_ULONG wndsize
= 1 << window
;
802 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
803 /* if a previously allocated window is big enough, keep it */
804 if (window
< 15 || window
> 21) return DECR_DATAFORMAT
;
805 if (LZX(actual_size
) < wndsize
) {
806 if (LZX(window
)) CAB(fdi
)->free(LZX(window
));
810 if (!(LZX(window
) = CAB(fdi
)->alloc(wndsize
))) return DECR_NOMEMORY
;
811 LZX(actual_size
) = wndsize
;
813 LZX(window_size
) = wndsize
;
815 /* initialize static tables */
816 memcpy(CAB(extra_bits
), bits
, sizeof(bits
));
817 memcpy(CAB(lzx_position_base
), base
, sizeof(base
));
819 /* calculate required position slots */
820 if (window
== 20) posn_slots
= 42;
821 else if (window
== 21) posn_slots
= 50;
822 else posn_slots
= window
<< 1;
824 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
826 LZX(R0
) = LZX(R1
) = LZX(R2
) = 1;
827 LZX(main_elements
) = LZX_NUM_CHARS
+ (posn_slots
<< 3);
828 LZX(header_read
) = 0;
829 LZX(frames_read
) = 0;
830 LZX(block_remaining
) = 0;
831 LZX(block_type
) = LZX_BLOCKTYPE_INVALID
;
832 LZX(intel_curpos
) = 0;
833 LZX(intel_started
) = 0;
834 LZX(window_posn
) = 0;
836 /* initialize tables to 0 (because deltas will be applied to them) */
837 memset(LZX(MAINTREE_len
), 0, sizeof(LZX(MAINTREE_len
)));
838 memset(LZX(LENGTH_len
), 0, sizeof(LZX(LENGTH_len
)));
843 /****************************************************
844 * NONEfdi_decomp(internal)
846 static int NONEfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
848 if (inlen
!= outlen
) return DECR_ILLEGALDATA
;
849 if (outlen
> CAB_BLOCKMAX
) return DECR_DATAFORMAT
;
850 memcpy(CAB(outbuf
), CAB(inbuf
), (size_t) inlen
);
854 /********************************************************
855 * Ziphuft_free (internal)
857 static void fdi_Ziphuft_free(FDI_Int
*fdi
, struct Ziphuft
*t
)
859 register struct Ziphuft
*p
, *q
;
861 /* Go through linked list, freeing from the allocated (t[-1]) address. */
871 /*********************************************************
872 * fdi_Ziphuft_build (internal)
874 static cab_LONG
fdi_Ziphuft_build(cab_ULONG
*b
, cab_ULONG n
, cab_ULONG s
, const cab_UWORD
*d
, const cab_UWORD
*e
,
875 struct Ziphuft
**t
, cab_LONG
*m
, fdi_decomp_state
*decomp_state
)
877 cab_ULONG a
; /* counter for codes of length k */
878 cab_ULONG el
; /* length of EOB code (value 256) */
879 cab_ULONG f
; /* i repeats in table every f entries */
880 cab_LONG g
; /* maximum code length */
881 cab_LONG h
; /* table level */
882 register cab_ULONG i
; /* counter, current code */
883 register cab_ULONG j
; /* counter */
884 register cab_LONG k
; /* number of bits in current code */
885 cab_LONG
*l
; /* stack of bits per table */
886 register cab_ULONG
*p
; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
887 register struct Ziphuft
*q
; /* points to current table */
888 struct Ziphuft r
; /* table entry for structure assignment */
889 register cab_LONG w
; /* bits before this table == (l * h) */
890 cab_ULONG
*xp
; /* pointer into x */
891 cab_LONG y
; /* number of dummy codes added */
892 cab_ULONG z
; /* number of entries in current table */
896 /* Generate counts for each bit length */
897 el
= n
> 256 ? b
[256] : ZIPBMAX
; /* set length of EOB code, if any */
899 for(i
= 0; i
< ZIPBMAX
+1; ++i
)
904 ZIP(c
)[*p
]++; p
++; /* assume all entries <= ZIPBMAX */
906 if (ZIP(c
)[0] == n
) /* null input--all zero length codes */
913 /* Find minimum and maximum length, bound *m by those */
914 for (j
= 1; j
<= ZIPBMAX
; j
++)
917 k
= j
; /* minimum code length */
918 if ((cab_ULONG
)*m
< j
)
920 for (i
= ZIPBMAX
; i
; i
--)
923 g
= i
; /* maximum code length */
924 if ((cab_ULONG
)*m
> i
)
927 /* Adjust last length count to fill out codes, if needed */
928 for (y
= 1 << j
; j
< i
; j
++, y
<<= 1)
929 if ((y
-= ZIP(c
)[j
]) < 0)
930 return 2; /* bad input: more codes than bits */
931 if ((y
-= ZIP(c
)[i
]) < 0)
935 /* Generate starting offsets LONGo the value table for each length */
937 p
= ZIP(c
) + 1; xp
= ZIP(x
) + 2;
939 { /* note that i == g from above */
943 /* Make a table of values in order of bit lengths */
947 ZIP(v
)[ZIP(x
)[j
]++] = i
;
951 /* Generate the Huffman codes and for each, make the table entries */
952 ZIP(x
)[0] = i
= 0; /* first Huffman code is zero */
953 p
= ZIP(v
); /* grab values in bit order */
954 h
= -1; /* no tables yet--level -1 */
955 w
= l
[-1] = 0; /* no bits decoded yet */
956 ZIP(u
)[0] = NULL
; /* just to keep compilers happy */
957 q
= NULL
; /* ditto */
960 /* go through the bit lengths (k already is bits in shortest code) */
966 /* here i is the Huffman code of length k bits for value *p */
967 /* make tables up to required level */
970 w
+= l
[h
++]; /* add bits already decoded */
972 /* compute minimum size table less than or equal to *m bits */
973 if ((z
= g
- w
) > (cab_ULONG
)*m
) /* upper limit */
975 if ((f
= 1 << (j
= k
- w
)) > a
+ 1) /* try a k-w bit table */
976 { /* too few codes for k-w bit table */
977 f
-= a
+ 1; /* deduct codes from patterns left */
979 while (++j
< z
) /* try smaller tables up to z bits */
981 if ((f
<<= 1) <= *++xp
)
982 break; /* enough codes to use up j bits */
983 f
-= *xp
; /* else deduct codes from patterns */
986 if ((cab_ULONG
)w
+ j
> el
&& (cab_ULONG
)w
< el
)
987 j
= el
- w
; /* make EOB code end at table */
988 z
= 1 << j
; /* table entries for j-bit table */
989 l
[h
] = j
; /* set table size in stack */
991 /* allocate and link in new table */
992 if (!(q
= CAB(fdi
)->alloc((z
+ 1)*sizeof(struct Ziphuft
))))
995 fdi_Ziphuft_free(CAB(fdi
), ZIP(u
)[0]);
996 return 3; /* not enough memory */
998 *t
= q
+ 1; /* link to list for Ziphuft_free() */
999 *(t
= &(q
->v
.t
)) = NULL
;
1000 ZIP(u
)[h
] = ++q
; /* table starts after link */
1002 /* connect to last table, if there is one */
1005 ZIP(x
)[h
] = i
; /* save pattern for backing up */
1006 r
.b
= (cab_UBYTE
)l
[h
-1]; /* bits to dump before this table */
1007 r
.e
= (cab_UBYTE
)(16 + j
); /* bits in this table */
1008 r
.v
.t
= q
; /* pointer to this table */
1009 j
= (i
& ((1 << w
) - 1)) >> (w
- l
[h
-1]);
1010 ZIP(u
)[h
-1][j
] = r
; /* connect to last table */
1014 /* set up table entry in r */
1015 r
.b
= (cab_UBYTE
)(k
- w
);
1016 if (p
>= ZIP(v
) + n
)
1017 r
.e
= 99; /* out of values--invalid code */
1020 r
.e
= (cab_UBYTE
)(*p
< 256 ? 16 : 15); /* 256 is end-of-block code */
1021 r
.v
.n
= *p
++; /* simple code is just the value */
1025 r
.e
= (cab_UBYTE
)e
[*p
- s
]; /* non-simple--look up in lists */
1026 r
.v
.n
= d
[*p
++ - s
];
1029 /* fill code-like entries with r */
1031 for (j
= i
>> w
; j
< z
; j
+= f
)
1034 /* backwards increment the k-bit code i */
1035 for (j
= 1 << (k
- 1); i
& j
; j
>>= 1)
1039 /* backup over finished tables */
1040 while ((i
& ((1 << w
) - 1)) != ZIP(x
)[h
])
1041 w
-= l
[--h
]; /* don't need to update q */
1045 /* return actual size of base table */
1048 /* Return true (1) if we were given an incomplete table */
1049 return y
!= 0 && g
!= 1;
1052 /*********************************************************
1053 * fdi_Zipinflate_codes (internal)
1055 static cab_LONG
fdi_Zipinflate_codes(const struct Ziphuft
*tl
, const struct Ziphuft
*td
,
1056 cab_LONG bl
, cab_LONG bd
, fdi_decomp_state
*decomp_state
)
1058 register cab_ULONG e
; /* table entry flag/number of extra bits */
1059 cab_ULONG n
, d
; /* length and index for copy */
1060 cab_ULONG w
; /* current window position */
1061 const struct Ziphuft
*t
; /* pointer to table entry */
1062 cab_ULONG ml
, md
; /* masks for bl and bd bits */
1063 register cab_ULONG b
; /* bit buffer */
1064 register cab_ULONG k
; /* number of bits in bit buffer */
1066 /* make local copies of globals */
1067 b
= ZIP(bb
); /* initialize bit buffer */
1069 w
= ZIP(window_posn
); /* initialize window position */
1071 /* inflate the coded data */
1072 ml
= Zipmask
[bl
]; /* precompute masks for speed */
1077 ZIPNEEDBITS((cab_ULONG
)bl
)
1078 if((e
= (t
= tl
+ (b
& ml
))->e
) > 16)
1086 } while ((e
= (t
= t
->v
.t
+ (b
& Zipmask
[e
]))->e
) > 16);
1088 if (e
== 16) /* then it's a literal */
1089 CAB(outbuf
)[w
++] = (cab_UBYTE
)t
->v
.n
;
1090 else /* it's an EOB or a length */
1092 /* exit if end of block */
1096 /* get length of block to copy */
1098 n
= t
->v
.n
+ (b
& Zipmask
[e
]);
1101 /* decode distance of block to copy */
1102 ZIPNEEDBITS((cab_ULONG
)bd
)
1103 if ((e
= (t
= td
+ (b
& md
))->e
) > 16)
1110 } while ((e
= (t
= t
->v
.t
+ (b
& Zipmask
[e
]))->e
) > 16);
1113 d
= w
- t
->v
.n
- (b
& Zipmask
[e
]);
1118 e
= ZIPWSIZE
- max(d
, w
);
1123 CAB(outbuf
)[w
++] = CAB(outbuf
)[d
++];
1129 /* restore the globals from the locals */
1130 ZIP(window_posn
) = w
; /* restore global window pointer */
1131 ZIP(bb
) = b
; /* restore global bit buffer */
1138 /***********************************************************
1139 * Zipinflate_stored (internal)
1141 static cab_LONG
fdi_Zipinflate_stored(fdi_decomp_state
*decomp_state
)
1142 /* "decompress" an inflated type 0 (stored) block. */
1144 cab_ULONG n
; /* number of bytes in block */
1145 cab_ULONG w
; /* current window position */
1146 register cab_ULONG b
; /* bit buffer */
1147 register cab_ULONG k
; /* number of bits in bit buffer */
1149 /* make local copies of globals */
1150 b
= ZIP(bb
); /* initialize bit buffer */
1152 w
= ZIP(window_posn
); /* initialize window position */
1154 /* go to byte boundary */
1158 /* get the length and its complement */
1163 if (n
!= ((~b
) & 0xffff))
1164 return 1; /* error in compressed data */
1167 /* read and output the compressed data */
1171 CAB(outbuf
)[w
++] = (cab_UBYTE
)b
;
1175 /* restore the globals from the locals */
1176 ZIP(window_posn
) = w
; /* restore global window pointer */
1177 ZIP(bb
) = b
; /* restore global bit buffer */
1182 /******************************************************
1183 * fdi_Zipinflate_fixed (internal)
1185 static cab_LONG
fdi_Zipinflate_fixed(fdi_decomp_state
*decomp_state
)
1187 struct Ziphuft
*fixed_tl
;
1188 struct Ziphuft
*fixed_td
;
1189 cab_LONG fixed_bl
, fixed_bd
;
1190 cab_LONG i
; /* temporary variable */
1196 for(i
= 0; i
< 144; i
++)
1202 for(; i
< 288; i
++) /* make a complete, but wrong code set */
1205 if((i
= fdi_Ziphuft_build(l
, 288, 257, Zipcplens
, Zipcplext
, &fixed_tl
, &fixed_bl
, decomp_state
)))
1208 /* distance table */
1209 for(i
= 0; i
< 30; i
++) /* make an incomplete code set */
1212 if((i
= fdi_Ziphuft_build(l
, 30, 0, Zipcpdist
, Zipcpdext
, &fixed_td
, &fixed_bd
, decomp_state
)) > 1)
1214 fdi_Ziphuft_free(CAB(fdi
), fixed_tl
);
1218 /* decompress until an end-of-block code */
1219 i
= fdi_Zipinflate_codes(fixed_tl
, fixed_td
, fixed_bl
, fixed_bd
, decomp_state
);
1221 fdi_Ziphuft_free(CAB(fdi
), fixed_td
);
1222 fdi_Ziphuft_free(CAB(fdi
), fixed_tl
);
1226 /**************************************************************
1227 * fdi_Zipinflate_dynamic (internal)
1229 static cab_LONG
fdi_Zipinflate_dynamic(fdi_decomp_state
*decomp_state
)
1230 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1232 cab_LONG i
; /* temporary variables */
1235 cab_ULONG l
; /* last length */
1236 cab_ULONG m
; /* mask for bit lengths table */
1237 cab_ULONG n
; /* number of lengths to get */
1238 struct Ziphuft
*tl
; /* literal/length code table */
1239 struct Ziphuft
*td
; /* distance code table */
1240 cab_LONG bl
; /* lookup bits for tl */
1241 cab_LONG bd
; /* lookup bits for td */
1242 cab_ULONG nb
; /* number of bit length codes */
1243 cab_ULONG nl
; /* number of literal/length codes */
1244 cab_ULONG nd
; /* number of distance codes */
1245 register cab_ULONG b
; /* bit buffer */
1246 register cab_ULONG k
; /* number of bits in bit buffer */
1248 /* make local bit buffer */
1253 /* read in table lengths */
1255 nl
= 257 + (b
& 0x1f); /* number of literal/length codes */
1258 nd
= 1 + (b
& 0x1f); /* number of distance codes */
1261 nb
= 4 + (b
& 0xf); /* number of bit length codes */
1263 if(nl
> 288 || nd
> 32)
1264 return 1; /* bad lengths */
1266 /* read in bit-length-code lengths */
1267 for(j
= 0; j
< nb
; j
++)
1270 ll
[Zipborder
[j
]] = b
& 7;
1274 ll
[Zipborder
[j
]] = 0;
1276 /* build decoding table for trees--single level, 7 bit lookup */
1278 if((i
= fdi_Ziphuft_build(ll
, 19, 19, NULL
, NULL
, &tl
, &bl
, decomp_state
)) != 0)
1281 fdi_Ziphuft_free(CAB(fdi
), tl
);
1282 return i
; /* incomplete code set */
1285 /* read in literal and distance code lengths */
1289 while((cab_ULONG
)i
< n
)
1291 ZIPNEEDBITS((cab_ULONG
)bl
)
1292 j
= (td
= tl
+ (b
& m
))->b
;
1295 if (j
< 16) /* length of code in bits (0..15) */
1296 ll
[i
++] = l
= j
; /* save last length in l */
1297 else if (j
== 16) /* repeat last length 3 to 6 times */
1302 if((cab_ULONG
)i
+ j
> n
)
1307 else if (j
== 17) /* 3 to 10 zero length codes */
1312 if ((cab_ULONG
)i
+ j
> n
)
1318 else /* j == 18: 11 to 138 zero length codes */
1321 j
= 11 + (b
& 0x7f);
1323 if ((cab_ULONG
)i
+ j
> n
)
1331 /* free decoding table for trees */
1332 fdi_Ziphuft_free(CAB(fdi
), tl
);
1334 /* restore the global bit buffer */
1338 /* build the decoding tables for literal/length and distance codes */
1340 if((i
= fdi_Ziphuft_build(ll
, nl
, 257, Zipcplens
, Zipcplext
, &tl
, &bl
, decomp_state
)) != 0)
1343 fdi_Ziphuft_free(CAB(fdi
), tl
);
1344 return i
; /* incomplete code set */
1347 fdi_Ziphuft_build(ll
+ nl
, nd
, 0, Zipcpdist
, Zipcpdext
, &td
, &bd
, decomp_state
);
1349 /* decompress until an end-of-block code */
1350 if(fdi_Zipinflate_codes(tl
, td
, bl
, bd
, decomp_state
))
1353 /* free the decoding tables, return */
1354 fdi_Ziphuft_free(CAB(fdi
), tl
);
1355 fdi_Ziphuft_free(CAB(fdi
), td
);
1359 /*****************************************************
1360 * fdi_Zipinflate_block (internal)
1362 static cab_LONG
fdi_Zipinflate_block(cab_LONG
*e
, fdi_decomp_state
*decomp_state
) /* e == last block flag */
1363 { /* decompress an inflated block */
1364 cab_ULONG t
; /* block type */
1365 register cab_ULONG b
; /* bit buffer */
1366 register cab_ULONG k
; /* number of bits in bit buffer */
1368 /* make local bit buffer */
1372 /* read in last block bit */
1374 *e
= (cab_LONG
)b
& 1;
1377 /* read in block type */
1382 /* restore the global bit buffer */
1386 /* inflate that block type */
1388 return fdi_Zipinflate_dynamic(decomp_state
);
1390 return fdi_Zipinflate_stored(decomp_state
);
1392 return fdi_Zipinflate_fixed(decomp_state
);
1393 /* bad block type */
1397 /****************************************************
1398 * ZIPfdi_decomp(internal)
1400 static int ZIPfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
1402 cab_LONG e
; /* last block flag */
1404 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1406 ZIP(inpos
) = CAB(inbuf
);
1407 ZIP(bb
) = ZIP(bk
) = ZIP(window_posn
) = 0;
1408 if(outlen
> ZIPWSIZE
)
1409 return DECR_DATAFORMAT
;
1411 /* CK = Chris Kirmse, official Microsoft purloiner */
1412 if(ZIP(inpos
)[0] != 0x43 || ZIP(inpos
)[1] != 0x4B)
1413 return DECR_ILLEGALDATA
;
1417 if(fdi_Zipinflate_block(&e
, decomp_state
))
1418 return DECR_ILLEGALDATA
;
1421 /* return success */
1425 /*******************************************************************
1426 * QTMfdi_decomp(internal)
1428 static int QTMfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
1430 cab_UBYTE
*inpos
= CAB(inbuf
);
1431 cab_UBYTE
*window
= QTM(window
);
1432 cab_UBYTE
*runsrc
, *rundest
;
1433 cab_ULONG window_posn
= QTM(window_posn
);
1434 cab_ULONG window_size
= QTM(window_size
);
1436 /* used by bitstream macros */
1437 register int bitsleft
, bitrun
, bitsneed
;
1438 register cab_ULONG bitbuf
;
1440 /* used by GET_SYMBOL */
1445 int extra
, togo
= outlen
, match_length
= 0, copy_length
;
1446 cab_UBYTE selector
, sym
;
1447 cab_ULONG match_offset
= 0;
1449 cab_UWORD H
= 0xFFFF, L
= 0, C
;
1451 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1453 /* read initial value of C */
1457 /* apply 2^x-1 mask */
1458 window_posn
&= window_size
- 1;
1459 /* runs can't straddle the window wraparound */
1460 if ((window_posn
+ togo
) > window_size
) {
1461 TRACE("straddled run\n");
1462 return DECR_DATAFORMAT
;
1466 GET_SYMBOL(model7
, selector
);
1469 GET_SYMBOL(model00
, sym
); window
[window_posn
++] = sym
; togo
--;
1472 GET_SYMBOL(model40
, sym
); window
[window_posn
++] = sym
; togo
--;
1475 GET_SYMBOL(model80
, sym
); window
[window_posn
++] = sym
; togo
--;
1478 GET_SYMBOL(modelC0
, sym
); window
[window_posn
++] = sym
; togo
--;
1482 /* selector 4 = fixed length of 3 */
1483 GET_SYMBOL(model4
, sym
);
1484 Q_READ_BITS(extra
, CAB(q_extra_bits
)[sym
]);
1485 match_offset
= CAB(q_position_base
)[sym
] + extra
+ 1;
1490 /* selector 5 = fixed length of 4 */
1491 GET_SYMBOL(model5
, sym
);
1492 Q_READ_BITS(extra
, CAB(q_extra_bits
)[sym
]);
1493 match_offset
= CAB(q_position_base
)[sym
] + extra
+ 1;
1498 /* selector 6 = variable length */
1499 GET_SYMBOL(model6len
, sym
);
1500 Q_READ_BITS(extra
, CAB(q_length_extra
)[sym
]);
1501 match_length
= CAB(q_length_base
)[sym
] + extra
+ 5;
1502 GET_SYMBOL(model6pos
, sym
);
1503 Q_READ_BITS(extra
, CAB(q_extra_bits
)[sym
]);
1504 match_offset
= CAB(q_position_base
)[sym
] + extra
+ 1;
1508 TRACE("Selector is bogus\n");
1509 return DECR_ILLEGALDATA
;
1512 /* if this is a match */
1513 if (selector
>= 4) {
1514 rundest
= window
+ window_posn
;
1515 togo
-= match_length
;
1517 /* copy any wrapped around source data */
1518 if (window_posn
>= match_offset
) {
1520 runsrc
= rundest
- match_offset
;
1522 runsrc
= rundest
+ (window_size
- match_offset
);
1523 copy_length
= match_offset
- window_posn
;
1524 if (copy_length
< match_length
) {
1525 match_length
-= copy_length
;
1526 window_posn
+= copy_length
;
1527 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1531 window_posn
+= match_length
;
1533 /* copy match data - no worries about destination wraps */
1534 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1536 } /* while (togo > 0) */
1539 TRACE("Frame overflow, this_run = %d\n", togo
);
1540 return DECR_ILLEGALDATA
;
1543 memcpy(CAB(outbuf
), window
+ ((!window_posn
) ? window_size
: window_posn
) -
1546 QTM(window_posn
) = window_posn
;
1550 /************************************************************
1551 * fdi_lzx_read_lens (internal)
1553 static int fdi_lzx_read_lens(cab_UBYTE
*lens
, cab_ULONG first
, cab_ULONG last
, struct lzx_bits
*lb
,
1554 fdi_decomp_state
*decomp_state
) {
1558 register cab_ULONG bitbuf
= lb
->bb
;
1559 register int bitsleft
= lb
->bl
;
1560 cab_UBYTE
*inpos
= lb
->ip
;
1563 for (x
= 0; x
< 20; x
++) {
1565 LENTABLE(PRETREE
)[x
] = y
;
1567 BUILD_TABLE(PRETREE
);
1569 for (x
= first
; x
< last
; ) {
1570 READ_HUFFSYM(PRETREE
, z
);
1572 READ_BITS(y
, 4); y
+= 4;
1573 while (y
--) lens
[x
++] = 0;
1576 READ_BITS(y
, 5); y
+= 20;
1577 while (y
--) lens
[x
++] = 0;
1580 READ_BITS(y
, 1); y
+= 4;
1581 READ_HUFFSYM(PRETREE
, z
);
1582 z
= lens
[x
] - z
; if (z
< 0) z
+= 17;
1583 while (y
--) lens
[x
++] = z
;
1586 z
= lens
[x
] - z
; if (z
< 0) z
+= 17;
1597 /*******************************************************
1598 * LZXfdi_decomp(internal)
1600 static int LZXfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
) {
1601 cab_UBYTE
*inpos
= CAB(inbuf
);
1602 const cab_UBYTE
*endinp
= inpos
+ inlen
;
1603 cab_UBYTE
*window
= LZX(window
);
1604 cab_UBYTE
*runsrc
, *rundest
;
1605 cab_UWORD
*hufftbl
; /* used in READ_HUFFSYM macro as chosen decoding table */
1607 cab_ULONG window_posn
= LZX(window_posn
);
1608 cab_ULONG window_size
= LZX(window_size
);
1609 cab_ULONG R0
= LZX(R0
);
1610 cab_ULONG R1
= LZX(R1
);
1611 cab_ULONG R2
= LZX(R2
);
1613 register cab_ULONG bitbuf
;
1614 register int bitsleft
;
1615 cab_ULONG match_offset
, i
,j
,k
; /* ijk used in READ_HUFFSYM macro */
1616 struct lzx_bits lb
; /* used in READ_LENGTHS macro */
1618 int togo
= outlen
, this_run
, main_element
, aligned_bits
;
1619 int match_length
, copy_length
, length_footer
, extra
, verbatim_bits
;
1621 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1625 /* read header if necessary */
1626 if (!LZX(header_read
)) {
1628 READ_BITS(k
, 1); if (k
) { READ_BITS(i
,16); READ_BITS(j
,16); }
1629 LZX(intel_filesize
) = (i
<< 16) | j
; /* or 0 if not encoded */
1630 LZX(header_read
) = 1;
1633 /* main decoding loop */
1635 /* last block finished, new block expected */
1636 if (LZX(block_remaining
) == 0) {
1637 if (LZX(block_type
) == LZX_BLOCKTYPE_UNCOMPRESSED
) {
1638 if (LZX(block_length
) & 1) inpos
++; /* realign bitstream to word */
1642 READ_BITS(LZX(block_type
), 3);
1645 LZX(block_remaining
) = LZX(block_length
) = (i
<< 8) | j
;
1647 switch (LZX(block_type
)) {
1648 case LZX_BLOCKTYPE_ALIGNED
:
1649 for (i
= 0; i
< 8; i
++) { READ_BITS(j
, 3); LENTABLE(ALIGNED
)[i
] = j
; }
1650 BUILD_TABLE(ALIGNED
);
1651 /* rest of aligned header is same as verbatim */
1653 case LZX_BLOCKTYPE_VERBATIM
:
1654 READ_LENGTHS(MAINTREE
, 0, 256, fdi_lzx_read_lens
);
1655 READ_LENGTHS(MAINTREE
, 256, LZX(main_elements
), fdi_lzx_read_lens
);
1656 BUILD_TABLE(MAINTREE
);
1657 if (LENTABLE(MAINTREE
)[0xE8] != 0) LZX(intel_started
) = 1;
1659 READ_LENGTHS(LENGTH
, 0, LZX_NUM_SECONDARY_LENGTHS
, fdi_lzx_read_lens
);
1660 BUILD_TABLE(LENGTH
);
1663 case LZX_BLOCKTYPE_UNCOMPRESSED
:
1664 LZX(intel_started
) = 1; /* because we can't assume otherwise */
1665 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1666 if (bitsleft
> 16) inpos
-= 2; /* and align the bitstream! */
1667 R0
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1668 R1
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1669 R2
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1673 return DECR_ILLEGALDATA
;
1677 /* buffer exhaustion check */
1678 if (inpos
> endinp
) {
1679 /* it's possible to have a file where the next run is less than
1680 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1681 * in building the tables will exhaust the buffer, so we should
1682 * allow for this, but not allow those accidentally read bits to
1683 * be used (so we check that there are at least 16 bits
1684 * remaining - in this boundary case they aren't really part of
1685 * the compressed data)
1687 if (inpos
> (endinp
+2) || bitsleft
< 16) return DECR_ILLEGALDATA
;
1690 while ((this_run
= LZX(block_remaining
)) > 0 && togo
> 0) {
1691 if (this_run
> togo
) this_run
= togo
;
1693 LZX(block_remaining
) -= this_run
;
1695 /* apply 2^x-1 mask */
1696 window_posn
&= window_size
- 1;
1697 /* runs can't straddle the window wraparound */
1698 if ((window_posn
+ this_run
) > window_size
)
1699 return DECR_DATAFORMAT
;
1701 switch (LZX(block_type
)) {
1703 case LZX_BLOCKTYPE_VERBATIM
:
1704 while (this_run
> 0) {
1705 READ_HUFFSYM(MAINTREE
, main_element
);
1707 if (main_element
< LZX_NUM_CHARS
) {
1708 /* literal: 0 to LZX_NUM_CHARS-1 */
1709 window
[window_posn
++] = main_element
;
1713 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1714 main_element
-= LZX_NUM_CHARS
;
1716 match_length
= main_element
& LZX_NUM_PRIMARY_LENGTHS
;
1717 if (match_length
== LZX_NUM_PRIMARY_LENGTHS
) {
1718 READ_HUFFSYM(LENGTH
, length_footer
);
1719 match_length
+= length_footer
;
1721 match_length
+= LZX_MIN_MATCH
;
1723 match_offset
= main_element
>> 3;
1725 if (match_offset
> 2) {
1726 /* not repeated offset */
1727 if (match_offset
!= 3) {
1728 extra
= CAB(extra_bits
)[match_offset
];
1729 READ_BITS(verbatim_bits
, extra
);
1730 match_offset
= CAB(lzx_position_base
)[match_offset
]
1731 - 2 + verbatim_bits
;
1737 /* update repeated offset LRU queue */
1738 R2
= R1
; R1
= R0
; R0
= match_offset
;
1740 else if (match_offset
== 0) {
1743 else if (match_offset
== 1) {
1745 R1
= R0
; R0
= match_offset
;
1747 else /* match_offset == 2 */ {
1749 R2
= R0
; R0
= match_offset
;
1752 rundest
= window
+ window_posn
;
1753 this_run
-= match_length
;
1755 /* copy any wrapped around source data */
1756 if (window_posn
>= match_offset
) {
1758 runsrc
= rundest
- match_offset
;
1760 runsrc
= rundest
+ (window_size
- match_offset
);
1761 copy_length
= match_offset
- window_posn
;
1762 if (copy_length
< match_length
) {
1763 match_length
-= copy_length
;
1764 window_posn
+= copy_length
;
1765 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1769 window_posn
+= match_length
;
1771 /* copy match data - no worries about destination wraps */
1772 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1777 case LZX_BLOCKTYPE_ALIGNED
:
1778 while (this_run
> 0) {
1779 READ_HUFFSYM(MAINTREE
, main_element
);
1781 if (main_element
< LZX_NUM_CHARS
) {
1782 /* literal: 0 to LZX_NUM_CHARS-1 */
1783 window
[window_posn
++] = main_element
;
1787 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1788 main_element
-= LZX_NUM_CHARS
;
1790 match_length
= main_element
& LZX_NUM_PRIMARY_LENGTHS
;
1791 if (match_length
== LZX_NUM_PRIMARY_LENGTHS
) {
1792 READ_HUFFSYM(LENGTH
, length_footer
);
1793 match_length
+= length_footer
;
1795 match_length
+= LZX_MIN_MATCH
;
1797 match_offset
= main_element
>> 3;
1799 if (match_offset
> 2) {
1800 /* not repeated offset */
1801 extra
= CAB(extra_bits
)[match_offset
];
1802 match_offset
= CAB(lzx_position_base
)[match_offset
] - 2;
1804 /* verbatim and aligned bits */
1806 READ_BITS(verbatim_bits
, extra
);
1807 match_offset
+= (verbatim_bits
<< 3);
1808 READ_HUFFSYM(ALIGNED
, aligned_bits
);
1809 match_offset
+= aligned_bits
;
1811 else if (extra
== 3) {
1812 /* aligned bits only */
1813 READ_HUFFSYM(ALIGNED
, aligned_bits
);
1814 match_offset
+= aligned_bits
;
1816 else if (extra
> 0) { /* extra==1, extra==2 */
1817 /* verbatim bits only */
1818 READ_BITS(verbatim_bits
, extra
);
1819 match_offset
+= verbatim_bits
;
1821 else /* extra == 0 */ {
1826 /* update repeated offset LRU queue */
1827 R2
= R1
; R1
= R0
; R0
= match_offset
;
1829 else if (match_offset
== 0) {
1832 else if (match_offset
== 1) {
1834 R1
= R0
; R0
= match_offset
;
1836 else /* match_offset == 2 */ {
1838 R2
= R0
; R0
= match_offset
;
1841 rundest
= window
+ window_posn
;
1842 this_run
-= match_length
;
1844 /* copy any wrapped around source data */
1845 if (window_posn
>= match_offset
) {
1847 runsrc
= rundest
- match_offset
;
1849 runsrc
= rundest
+ (window_size
- match_offset
);
1850 copy_length
= match_offset
- window_posn
;
1851 if (copy_length
< match_length
) {
1852 match_length
-= copy_length
;
1853 window_posn
+= copy_length
;
1854 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1858 window_posn
+= match_length
;
1860 /* copy match data - no worries about destination wraps */
1861 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1866 case LZX_BLOCKTYPE_UNCOMPRESSED
:
1867 if ((inpos
+ this_run
) > endinp
) return DECR_ILLEGALDATA
;
1868 memcpy(window
+ window_posn
, inpos
, (size_t) this_run
);
1869 inpos
+= this_run
; window_posn
+= this_run
;
1873 return DECR_ILLEGALDATA
; /* might as well */
1879 if (togo
!= 0) return DECR_ILLEGALDATA
;
1880 memcpy(CAB(outbuf
), window
+ ((!window_posn
) ? window_size
: window_posn
) -
1881 outlen
, (size_t) outlen
);
1883 LZX(window_posn
) = window_posn
;
1888 /* intel E8 decoding */
1889 if ((LZX(frames_read
)++ < 32768) && LZX(intel_filesize
) != 0) {
1890 if (outlen
<= 6 || !LZX(intel_started
)) {
1891 LZX(intel_curpos
) += outlen
;
1894 cab_UBYTE
*data
= CAB(outbuf
);
1895 cab_UBYTE
*dataend
= data
+ outlen
- 10;
1896 cab_LONG curpos
= LZX(intel_curpos
);
1897 cab_LONG filesize
= LZX(intel_filesize
);
1898 cab_LONG abs_off
, rel_off
;
1900 LZX(intel_curpos
) = curpos
+ outlen
;
1902 while (data
< dataend
) {
1903 if (*data
++ != 0xE8) { curpos
++; continue; }
1904 abs_off
= data
[0] | (data
[1]<<8) | (data
[2]<<16) | (data
[3]<<24);
1905 if ((abs_off
>= -curpos
) && (abs_off
< filesize
)) {
1906 rel_off
= (abs_off
>= 0) ? abs_off
- curpos
: abs_off
+ filesize
;
1907 data
[0] = (cab_UBYTE
) rel_off
;
1908 data
[1] = (cab_UBYTE
) (rel_off
>> 8);
1909 data
[2] = (cab_UBYTE
) (rel_off
>> 16);
1910 data
[3] = (cab_UBYTE
) (rel_off
>> 24);
1920 /**********************************************************
1921 * fdi_decomp (internal)
1923 * Decompress the requested number of bytes. If savemode is zero,
1924 * do not save the output anywhere, just plow through blocks until we
1925 * reach the specified (uncompressed) distance from the starting point,
1926 * and remember the position of the cabfile pointer (and which cabfile)
1927 * after we are done; otherwise, save the data out to CAB(filehf),
1928 * decompressing the requested number of bytes and writing them out. This
1929 * is also where we jump to additional cabinets in the case of split
1930 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1932 static int fdi_decomp(const struct fdi_file
*fi
, int savemode
, fdi_decomp_state
*decomp_state
,
1933 char *pszCabPath
, PFNFDINOTIFY pfnfdin
, void *pvUser
)
1935 cab_ULONG bytes
= savemode
? fi
->length
: fi
->offset
- CAB(offset
);
1936 cab_UBYTE buf
[cfdata_SIZEOF
], *data
;
1937 cab_UWORD inlen
, len
, outlen
, cando
;
1940 fdi_decomp_state
*cab
= (savemode
&& CAB(decomp_cab
)) ? CAB(decomp_cab
) : decomp_state
;
1942 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi
, savemode
, bytes
);
1945 /* cando = the max number of bytes we can do */
1946 cando
= CAB(outlen
);
1947 if (cando
> bytes
) cando
= bytes
;
1950 if (cando
&& savemode
)
1951 CAB(fdi
)->write(CAB(filehf
), CAB(outpos
), cando
);
1953 CAB(outpos
) += cando
;
1954 CAB(outlen
) -= cando
;
1955 bytes
-= cando
; if (!bytes
) break;
1957 /* we only get here if we emptied the output buffer */
1959 /* read data header + data */
1961 while (outlen
== 0) {
1962 /* read the block header, skip the reserved part */
1963 if (CAB(fdi
)->read(cab
->cabhf
, buf
, cfdata_SIZEOF
) != cfdata_SIZEOF
)
1966 if (CAB(fdi
)->seek(cab
->cabhf
, cab
->mii
.block_resv
, SEEK_CUR
) == -1)
1969 /* we shouldn't get blocks over CAB_INPUTMAX in size */
1970 data
= CAB(inbuf
) + inlen
;
1971 len
= EndGetI16(buf
+cfdata_CompressedSize
);
1973 if (inlen
> CAB_INPUTMAX
) return DECR_INPUT
;
1974 if (CAB(fdi
)->read(cab
->cabhf
, data
, len
) != len
)
1977 /* clear two bytes after read-in data */
1978 data
[len
+1] = data
[len
+2] = 0;
1980 /* perform checksum test on the block (if one is stored) */
1981 cksum
= EndGetI32(buf
+cfdata_CheckSum
);
1982 if (cksum
&& cksum
!= checksum(buf
+4, 4, checksum(data
, len
, 0)))
1983 return DECR_CHECKSUM
; /* checksum is wrong */
1985 outlen
= EndGetI16(buf
+cfdata_UncompressedSize
);
1987 /* outlen=0 means this block was the last contiguous part
1988 of a split block, continued in the next cabinet */
1990 int pathlen
, filenamelen
;
1992 char fullpath
[MAX_PATH
], userpath
[256];
1993 FDINOTIFICATION fdin
;
1994 FDICABINETINFO fdici
;
1995 char emptystring
= '\0';
1997 BOOL success
= FALSE
;
1998 struct fdi_folder
*fol
= NULL
, *linkfol
= NULL
;
1999 struct fdi_file
*file
= NULL
, *linkfile
= NULL
;
2003 /* set up the next decomp_state... */
2007 if (!cab
->mii
.hasnext
) return DECR_INPUT
;
2009 if (!((cab
->next
= CAB(fdi
)->alloc(sizeof(fdi_decomp_state
)))))
2010 return DECR_NOMEMORY
;
2012 ZeroMemory(cab
->next
, sizeof(fdi_decomp_state
));
2014 /* copy pszCabPath to userpath */
2015 ZeroMemory(userpath
, 256);
2016 pathlen
= pszCabPath
? strlen(pszCabPath
) : 0;
2018 if (pathlen
< 256) /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2019 strcpy(userpath
, pszCabPath
);
2022 /* initial fdintNEXT_CABINET notification */
2023 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2024 fdin
.psz1
= cab
->mii
.nextname
? cab
->mii
.nextname
: &emptystring
;
2025 fdin
.psz2
= cab
->mii
.nextinfo
? cab
->mii
.nextinfo
: &emptystring
;
2026 fdin
.psz3
= userpath
;
2027 fdin
.fdie
= FDIERROR_NONE
;
2030 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2034 pathlen
= strlen(userpath
);
2035 filenamelen
= cab
->mii
.nextname
? strlen(cab
->mii
.nextname
) : 0;
2037 /* slight overestimation here to save CPU cycles in the developer's brain */
2038 if ((pathlen
+ filenamelen
+ 3) > MAX_PATH
) {
2039 ERR("MAX_PATH exceeded.\n");
2040 return DECR_ILLEGALDATA
;
2043 /* paste the path and filename together */
2046 strcpy(fullpath
, userpath
);
2047 if (fullpath
[pathlen
- 1] != '\\')
2048 strcat(fullpath
, "\\");
2051 strcat(fullpath
, cab
->mii
.nextname
);
2053 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath
));
2055 /* try to get a handle to the cabfile */
2056 cabhf
= CAB(fdi
)->open(fullpath
, _O_RDONLY
|_O_BINARY
, _S_IREAD
| _S_IWRITE
);
2058 /* no file. allow the user to try again */
2059 fdin
.fdie
= FDIERROR_CABINET_NOT_FOUND
;
2060 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2065 ERR("PFDI_OPEN returned zero for %s.\n", fullpath
);
2066 fdin
.fdie
= FDIERROR_CABINET_NOT_FOUND
;
2067 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2071 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2072 if (!FDI_read_entries(CAB(fdi
), cabhf
, &fdici
, &(cab
->next
->mii
))) {
2073 WARN("FDIIsCabinet failed.\n");
2074 CAB(fdi
)->close(cabhf
);
2075 fdin
.fdie
= FDIERROR_NOT_A_CABINET
;
2076 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2080 if ((fdici
.setID
!= cab
->setID
) || (fdici
.iCabinet
!= (cab
->iCabinet
+ 1))) {
2081 WARN("Wrong Cabinet.\n");
2082 CAB(fdi
)->close(cabhf
);
2083 fdin
.fdie
= FDIERROR_WRONG_CABINET
;
2084 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2092 /* cabinet notification */
2093 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2094 fdin
.setID
= fdici
.setID
;
2095 fdin
.iCabinet
= fdici
.iCabinet
;
2097 fdin
.psz1
= (cab
->next
->mii
.nextname
) ? cab
->next
->mii
.nextname
: &emptystring
;
2098 fdin
.psz2
= (cab
->next
->mii
.nextinfo
) ? cab
->next
->mii
.nextinfo
: &emptystring
;
2099 fdin
.psz3
= pszCabPath
;
2101 if (((*pfnfdin
)(fdintCABINET_INFO
, &fdin
))) return DECR_USERABORT
;
2103 cab
->next
->setID
= fdici
.setID
;
2104 cab
->next
->iCabinet
= fdici
.iCabinet
;
2105 cab
->next
->fdi
= CAB(fdi
);
2106 cab
->next
->filehf
= CAB(filehf
);
2107 cab
->next
->cabhf
= cabhf
;
2108 cab
->next
->decompress
= CAB(decompress
); /* crude, but unused anyhow */
2110 cab
= cab
->next
; /* advance to the next cabinet */
2113 for (i
= 0; i
< fdici
.cFolders
; i
++) {
2114 if (CAB(fdi
)->read(cab
->cabhf
, buf2
, cffold_SIZEOF
) != cffold_SIZEOF
)
2117 if (cab
->mii
.folder_resv
> 0)
2118 CAB(fdi
)->seek(cab
->cabhf
, cab
->mii
.folder_resv
, SEEK_CUR
);
2120 fol
= CAB(fdi
)->alloc(sizeof(struct fdi_folder
));
2122 ERR("out of memory!\n");
2123 return DECR_NOMEMORY
;
2125 ZeroMemory(fol
, sizeof(struct fdi_folder
));
2126 if (!(cab
->firstfol
)) cab
->firstfol
= fol
;
2128 fol
->offset
= (cab_off_t
) EndGetI32(buf2
+cffold_DataOffset
);
2129 fol
->num_blocks
= EndGetI16(buf2
+cffold_NumBlocks
);
2130 fol
->comp_type
= EndGetI16(buf2
+cffold_CompType
);
2133 linkfol
->next
= fol
;
2138 for (i
= 0; i
< fdici
.cFiles
; i
++) {
2139 if (CAB(fdi
)->read(cab
->cabhf
, buf2
, cffile_SIZEOF
) != cffile_SIZEOF
)
2142 file
= CAB(fdi
)->alloc(sizeof(struct fdi_file
));
2144 ERR("out of memory!\n");
2145 return DECR_NOMEMORY
;
2147 ZeroMemory(file
, sizeof(struct fdi_file
));
2148 if (!(cab
->firstfile
)) cab
->firstfile
= file
;
2150 file
->length
= EndGetI32(buf2
+cffile_UncompressedSize
);
2151 file
->offset
= EndGetI32(buf2
+cffile_FolderOffset
);
2152 file
->index
= EndGetI16(buf2
+cffile_FolderIndex
);
2153 file
->time
= EndGetI16(buf2
+cffile_Time
);
2154 file
->date
= EndGetI16(buf2
+cffile_Date
);
2155 file
->attribs
= EndGetI16(buf2
+cffile_Attribs
);
2156 file
->filename
= FDI_read_string(CAB(fdi
), cab
->cabhf
, fdici
.cbCabinet
);
2158 if (!file
->filename
) return DECR_INPUT
;
2161 linkfile
->next
= file
;
2166 cab
= cab
->next
; /* advance to the next cabinet */
2168 /* iterate files -- if we encounter the continued file, process it --
2169 otherwise, jump to the label above and keep looking */
2171 for (file
= cab
->firstfile
; (file
); file
= file
->next
) {
2172 if ((file
->index
& cffileCONTINUED_FROM_PREV
) == cffileCONTINUED_FROM_PREV
) {
2173 /* check to ensure a real match */
2174 if (lstrcmpiA(fi
->filename
, file
->filename
) == 0) {
2176 if (CAB(fdi
)->seek(cab
->cabhf
, cab
->firstfol
->offset
, SEEK_SET
) == -1)
2182 if (!success
) goto tryanothercab
; /* FIXME: shouldn't this trigger
2183 "Wrong Cabinet" notification? */
2187 /* decompress block */
2188 if ((err
= CAB(decompress
)(inlen
, outlen
, decomp_state
)))
2190 CAB(outlen
) = outlen
;
2191 CAB(outpos
) = CAB(outbuf
);
2194 CAB(decomp_cab
) = cab
;
2198 static void free_decompression_temps(FDI_Int
*fdi
, const struct fdi_folder
*fol
,
2199 fdi_decomp_state
*decomp_state
)
2201 switch (fol
->comp_type
& cffoldCOMPTYPE_MASK
) {
2202 case cffoldCOMPTYPE_LZX
:
2204 fdi
->free(LZX(window
));
2208 case cffoldCOMPTYPE_QUANTUM
:
2210 fdi
->free(QTM(window
));
2217 static void free_decompression_mem(FDI_Int
*fdi
, fdi_decomp_state
*decomp_state
)
2219 struct fdi_folder
*fol
;
2220 while (decomp_state
) {
2221 fdi_decomp_state
*prev_fds
;
2223 fdi
->close(CAB(cabhf
));
2225 /* free the storage remembered by mii */
2226 if (CAB(mii
).nextname
) fdi
->free(CAB(mii
).nextname
);
2227 if (CAB(mii
).nextinfo
) fdi
->free(CAB(mii
).nextinfo
);
2228 if (CAB(mii
).prevname
) fdi
->free(CAB(mii
).prevname
);
2229 if (CAB(mii
).previnfo
) fdi
->free(CAB(mii
).previnfo
);
2231 while (CAB(firstfol
)) {
2232 fol
= CAB(firstfol
);
2233 CAB(firstfol
) = CAB(firstfol
)->next
;
2236 while (CAB(firstfile
)) {
2237 struct fdi_file
*file
= CAB(firstfile
);
2238 if (file
->filename
) fdi
->free(file
->filename
);
2239 CAB(firstfile
) = CAB(firstfile
)->next
;
2242 prev_fds
= decomp_state
;
2243 decomp_state
= CAB(next
);
2244 fdi
->free(prev_fds
);
2248 /***********************************************************************
2249 * FDICopy (CABINET.22)
2251 * Iterates through the files in the Cabinet file indicated by name and
2252 * file-location. May chain forward to additional cabinets (typically
2253 * only one) if files which begin in this Cabinet are continued in another
2254 * cabinet. For each file which is partially contained in this cabinet,
2255 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2256 * notification to the pfnfdin callback. For each file which begins in
2257 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2258 * callback, and the file is optionally decompressed and saved to disk.
2259 * Notification is not provided for files which are not at least partially
2260 * contained in the specified cabinet file.
2262 * See below for a thorough explanation of the various notification
2266 * hfdi [I] An HFDI from FDICreate
2267 * pszCabinet [I] C-style string containing the filename of the cabinet
2268 * pszCabPath [I] C-style string containing the file path of the cabinet
2269 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2270 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2271 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2273 * pvUser [I] arbitrary void * value which is passed to callbacks.
2276 * TRUE if successful.
2277 * FALSE if unsuccessful (error information is provided in the ERF structure
2278 * associated with the provided decompression handle by FDICreate).
2282 * Two pointers to callback functions are provided as parameters to FDICopy:
2283 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2284 * types are as follows:
2286 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2287 * PFDINOTIFICATION pfdin );
2289 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2291 * You can create functions of this type using the FNFDINOTIFY() and
2292 * FNFDIDECRYPT() macros, respectively. For example:
2294 * FNFDINOTIFY(mycallback) {
2295 * / * use variables fdint and pfdin to process notification * /
2298 * The second callback, which could be used for decrypting encrypted data,
2299 * is not used at all.
2301 * Each notification informs the user of some event which has occurred during
2302 * decompression of the cabinet file; each notification is also an opportunity
2303 * for the callee to abort decompression. The information provided to the
2304 * callback and the meaning of the callback's return value vary drastically
2305 * across the various types of notification. The type of notification is the
2306 * fdint parameter; all other information is provided to the callback in
2307 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2308 * pfdin. The only part of that structure which is assigned for every callback
2309 * is the pv element, which contains the arbitrary value which was passed to
2310 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2311 * is highly dependent on fdint).
2313 * If you encounter unknown notifications, you should return zero if you want
2314 * decompression to continue (or -1 to abort). All strings used in the
2315 * callbacks are regular C-style strings. Detailed descriptions of each
2316 * notification type follow:
2318 * fdintCABINET_INFO:
2320 * This is the first notification provided after calling FDICopy, and provides
2321 * the user with various information about the cabinet. Note that this is
2322 * called for each cabinet FDICopy opens, not just the first one. In the
2323 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2324 * next cabinet file in the set after the one just loaded (if any), psz2
2325 * contains a pointer to the name or "info" of the next disk, psz3
2326 * contains a pointer to the file-path of the current cabinet, setID
2327 * contains an arbitrary constant associated with this set of cabinet files,
2328 * and iCabinet contains the numerical index of the current cabinet within
2329 * that set. Return zero, or -1 to abort.
2331 * fdintPARTIAL_FILE:
2333 * This notification is provided when FDICopy encounters a part of a file
2334 * contained in this cabinet which is missing its beginning. Files can be
2335 * split across cabinets, so this is not necessarily an abnormality; it just
2336 * means that the file in question begins in another cabinet. No file
2337 * corresponding to this notification is extracted from the cabinet. In the
2338 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2339 * partial file, psz2 contains a pointer to the file name of the cabinet in
2340 * which this file begins, and psz3 contains a pointer to the disk name or
2341 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2345 * This notification is provided when FDICopy encounters a file which starts
2346 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2347 * look for files in cabinets after the first one). One notification will be
2348 * sent for each such file, before the file is decompressed. By returning
2349 * zero, the callback can instruct FDICopy to skip the file. In the structure
2350 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2351 * the size of the file (uncompressed), attribs contains the file attributes,
2352 * and date and time contain the date and time of the file. attributes, date,
2353 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2354 * for the entire cabinet, 0 to skip just this file but continue scanning the
2355 * cabinet for more files, or an FDIClose()-compatible file-handle.
2357 * fdintCLOSE_FILE_INFO:
2359 * This notification is important, don't forget to implement it. This
2360 * notification indicates that a file has been successfully uncompressed and
2361 * written to disk. Upon receipt of this notification, the callee is expected
2362 * to close the file handle, to set the attributes and date/time of the
2363 * closed file, and possibly to execute the file. In the structure pointed to
2364 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2365 * open file handle (close it), cb contains 1 or zero, indicating respectively
2366 * that the callee should or should not execute the file, and date, time
2367 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2368 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2369 * do so. Return TRUE, or FALSE to abort decompression.
2371 * fdintNEXT_CABINET:
2373 * This notification is called when FDICopy must load in another cabinet. This
2374 * can occur when a file's data is "split" across multiple cabinets. The
2375 * callee has the opportunity to request that FDICopy look in a different file
2376 * path for the specified cabinet file, by writing that data into a provided
2377 * buffer (see below for more information). This notification will be received
2378 * more than once per-cabinet in the instance that FDICopy failed to find a
2379 * valid cabinet at the location specified by the first per-cabinet
2380 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2381 * structure pointed to by pfdin indicates the error which prevented FDICopy
2382 * from proceeding successfully. Return zero to indicate success, or -1 to
2383 * indicate failure and abort FDICopy.
2385 * Upon receipt of this notification, the structure pointed to by pfdin will
2386 * contain the following values: psz1 pointing to the name of the cabinet
2387 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2388 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2389 * and fdie containing either FDIERROR_NONE, or one of the following:
2391 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2392 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2393 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2394 * FDIERROR_WRONG_CABINET.
2396 * The callee may choose to change the path where FDICopy will look for the
2397 * cabinet after this notification. To do so, the caller may write the new
2398 * pathname to the buffer pointed to by psz3, which is 256 characters in
2399 * length, including the terminating null character, before returning zero.
2403 * Undocumented and unimplemented in wine, this seems to be sent each time
2404 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2405 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2406 * provides information about the current cabinet instead of the next one....
2407 * this is just a guess, it has not been looked at closely.
2412 BOOL __cdecl
FDICopy(
2417 PFNFDINOTIFY pfnfdin
,
2418 PFNFDIDECRYPT pfnfdid
,
2421 FDICABINETINFO fdici
;
2422 FDINOTIFICATION fdin
;
2423 INT_PTR cabhf
, filehf
= 0;
2425 char fullpath
[MAX_PATH
];
2426 size_t pathlen
, filenamelen
;
2427 char emptystring
= '\0';
2429 struct fdi_folder
*fol
= NULL
, *linkfol
= NULL
;
2430 struct fdi_file
*file
= NULL
, *linkfile
= NULL
;
2431 fdi_decomp_state
*decomp_state
;
2432 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
2434 TRACE("(hfdi == ^%p, pszCabinet == %s, pszCabPath == %s, flags == %x, "
2435 "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2436 hfdi
, debugstr_a(pszCabinet
), debugstr_a(pszCabPath
), flags
, pfnfdin
, pfnfdid
, pvUser
);
2438 if (!fdi
) return FALSE
;
2440 if (!(decomp_state
= fdi
->alloc(sizeof(fdi_decomp_state
))))
2442 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2445 ZeroMemory(decomp_state
, sizeof(fdi_decomp_state
));
2447 pathlen
= pszCabPath
? strlen(pszCabPath
) : 0;
2448 filenamelen
= pszCabinet
? strlen(pszCabinet
) : 0;
2450 /* slight overestimation here to save CPU cycles in the developer's brain */
2451 if ((pathlen
+ filenamelen
+ 3) > MAX_PATH
) {
2452 ERR("MAX_PATH exceeded.\n");
2453 fdi
->free(decomp_state
);
2454 set_error( fdi
, FDIERROR_CABINET_NOT_FOUND
, ERROR_FILE_NOT_FOUND
);
2458 /* paste the path and filename together */
2461 strcpy(fullpath
, pszCabPath
);
2463 strcat(fullpath
, pszCabinet
);
2465 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath
));
2467 /* get a handle to the cabfile */
2468 cabhf
= fdi
->open(fullpath
, _O_RDONLY
|_O_BINARY
, _S_IREAD
| _S_IWRITE
);
2470 fdi
->free(decomp_state
);
2471 set_error( fdi
, FDIERROR_CABINET_NOT_FOUND
, 0 );
2472 SetLastError(ERROR_FILE_NOT_FOUND
);
2476 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2477 if (!FDI_read_entries(fdi
, cabhf
, &fdici
, &(CAB(mii
)))) {
2478 WARN("FDI_read_entries failed: %u\n", fdi
->perf
->erfOper
);
2479 fdi
->free(decomp_state
);
2484 /* cabinet notification */
2485 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2486 fdin
.setID
= fdici
.setID
;
2487 fdin
.iCabinet
= fdici
.iCabinet
;
2489 fdin
.psz1
= (CAB(mii
).nextname
) ? CAB(mii
).nextname
: &emptystring
;
2490 fdin
.psz2
= (CAB(mii
).nextinfo
) ? CAB(mii
).nextinfo
: &emptystring
;
2491 fdin
.psz3
= pszCabPath
;
2493 if (((*pfnfdin
)(fdintCABINET_INFO
, &fdin
))) {
2494 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2498 CAB(setID
) = fdici
.setID
;
2499 CAB(iCabinet
) = fdici
.iCabinet
;
2503 for (i
= 0; i
< fdici
.cFolders
; i
++) {
2504 if (fdi
->read(cabhf
, buf
, cffold_SIZEOF
) != cffold_SIZEOF
) {
2505 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2509 if (CAB(mii
).folder_resv
> 0)
2510 fdi
->seek(cabhf
, CAB(mii
).folder_resv
, SEEK_CUR
);
2512 fol
= fdi
->alloc(sizeof(struct fdi_folder
));
2514 ERR("out of memory!\n");
2515 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2518 ZeroMemory(fol
, sizeof(struct fdi_folder
));
2519 if (!CAB(firstfol
)) CAB(firstfol
) = fol
;
2521 fol
->offset
= (cab_off_t
) EndGetI32(buf
+cffold_DataOffset
);
2522 fol
->num_blocks
= EndGetI16(buf
+cffold_NumBlocks
);
2523 fol
->comp_type
= EndGetI16(buf
+cffold_CompType
);
2526 linkfol
->next
= fol
;
2531 for (i
= 0; i
< fdici
.cFiles
; i
++) {
2532 if (fdi
->read(cabhf
, buf
, cffile_SIZEOF
) != cffile_SIZEOF
) {
2533 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2537 file
= fdi
->alloc(sizeof(struct fdi_file
));
2539 ERR("out of memory!\n");
2540 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2543 ZeroMemory(file
, sizeof(struct fdi_file
));
2544 if (!CAB(firstfile
)) CAB(firstfile
) = file
;
2546 file
->length
= EndGetI32(buf
+cffile_UncompressedSize
);
2547 file
->offset
= EndGetI32(buf
+cffile_FolderOffset
);
2548 file
->index
= EndGetI16(buf
+cffile_FolderIndex
);
2549 file
->time
= EndGetI16(buf
+cffile_Time
);
2550 file
->date
= EndGetI16(buf
+cffile_Date
);
2551 file
->attribs
= EndGetI16(buf
+cffile_Attribs
);
2552 file
->filename
= FDI_read_string(fdi
, cabhf
, fdici
.cbCabinet
);
2554 if (!file
->filename
) {
2555 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2560 linkfile
->next
= file
;
2564 for (file
= CAB(firstfile
); (file
); file
= file
->next
) {
2567 * FIXME: This implementation keeps multiple cabinet files open at once
2568 * when encountering a split cabinet. It is a quirk of this implementation
2569 * that sometimes we decrypt the same block of data more than once, to find
2570 * the right starting point for a file, moving the file-pointer backwards.
2571 * If we kept a cache of certain file-pointer information, we could eliminate
2572 * that behavior... in fact I am not sure that the caching we already have
2573 * is not sufficient.
2575 * The current implementation seems to work fine in straightforward situations
2576 * where all the cabinet files needed for decryption are simultaneously
2577 * available. But presumably, the API is supposed to support cabinets which
2578 * are split across multiple CDROMS; we may need to change our implementation
2579 * to strictly serialize it's file usage so that it opens only one cabinet
2580 * at a time. Some experimentation with Windows is needed to figure out the
2581 * precise semantics required. The relevant code is here and in fdi_decomp().
2584 /* partial-file notification */
2585 if ((file
->index
& cffileCONTINUED_FROM_PREV
) == cffileCONTINUED_FROM_PREV
) {
2587 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2588 * and perform some tests to figure out the right behavior. The SDK says
2589 * FDICopy will notify the user of the filename and "disk name" (info) of
2590 * the cabinet where the spanning file /started/.
2592 * That would certainly be convenient for the API-user, who could abort,
2593 * everything (or parallelize, if that's allowed (it is in wine)), and call
2594 * FDICopy again with the provided filename, so as to avoid partial file
2595 * notification and successfully unpack. This task could be quite unpleasant
2596 * from wine's perspective: the information specifying the "start cabinet" for
2597 * a file is associated nowhere with the file header and is not to be found in
2598 * the cabinet header. We have only the index of the cabinet wherein the folder
2599 * begins, which contains the file. To find that cabinet, we must consider the
2600 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2601 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2604 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2605 * cabinet other than the active one might be at another filepath than the
2606 * current one, or on another CDROM. This could get rather dicey, especially
2607 * if we imagine parallelized access to the FDICopy API.
2609 * The current implementation punts -- it just returns the previous cabinet and
2610 * it's info from the header of this cabinet. This provides the right answer in
2611 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2614 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2616 fdin
.psz1
= (char *)file
->filename
;
2617 fdin
.psz2
= (CAB(mii
).prevname
) ? CAB(mii
).prevname
: &emptystring
;
2618 fdin
.psz3
= (CAB(mii
).previnfo
) ? CAB(mii
).previnfo
: &emptystring
;
2620 if (((*pfnfdin
)(fdintPARTIAL_FILE
, &fdin
))) {
2621 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2624 /* I don't think we are supposed to decompress partial files. This prevents it. */
2625 file
->oppressed
= TRUE
;
2627 if (file
->oppressed
) {
2630 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2632 fdin
.psz1
= (char *)file
->filename
;
2633 fdin
.cb
= file
->length
;
2634 fdin
.date
= file
->date
;
2635 fdin
.time
= file
->time
;
2636 fdin
.attribs
= file
->attribs
;
2637 if ((filehf
= ((*pfnfdin
)(fdintCOPY_FILE
, &fdin
))) == -1) {
2638 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2644 /* find the folder for this file if necc. */
2646 fol
= CAB(firstfol
);
2647 if ((file
->index
& cffileCONTINUED_TO_NEXT
) == cffileCONTINUED_TO_NEXT
) {
2648 /* pick the last folder */
2649 while (fol
->next
) fol
= fol
->next
;
2653 for (i2
= 0; (i2
< file
->index
); i2
++)
2654 if (fol
->next
) /* bug resistance, should always be true */
2660 cab_UWORD comptype
= fol
->comp_type
;
2661 int ct1
= comptype
& cffoldCOMPTYPE_MASK
;
2662 int ct2
= CAB(current
) ? (CAB(current
)->comp_type
& cffoldCOMPTYPE_MASK
) : 0;
2665 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file
->filename
));
2667 /* set up decomp_state */
2669 CAB(filehf
) = filehf
;
2671 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2672 if ((ct1
!= ct2
) || (CAB(current
) != fol
) || (file
->offset
< CAB(offset
))) {
2674 TRACE("Resetting folder for file %s.\n", debugstr_a(file
->filename
));
2676 /* free stuff for the old decompressor */
2678 case cffoldCOMPTYPE_LZX
:
2680 fdi
->free(LZX(window
));
2684 case cffoldCOMPTYPE_QUANTUM
:
2686 fdi
->free(QTM(window
));
2692 CAB(decomp_cab
) = NULL
;
2693 CAB(fdi
)->seek(CAB(cabhf
), fol
->offset
, SEEK_SET
);
2697 /* initialize the new decompressor */
2699 case cffoldCOMPTYPE_NONE
:
2700 CAB(decompress
) = NONEfdi_decomp
;
2702 case cffoldCOMPTYPE_MSZIP
:
2703 CAB(decompress
) = ZIPfdi_decomp
;
2705 case cffoldCOMPTYPE_QUANTUM
:
2706 CAB(decompress
) = QTMfdi_decomp
;
2707 err
= QTMfdi_init((comptype
>> 8) & 0x1f, (comptype
>> 4) & 0xF, decomp_state
);
2709 case cffoldCOMPTYPE_LZX
:
2710 CAB(decompress
) = LZXfdi_decomp
;
2711 err
= LZXfdi_init((comptype
>> 8) & 0x1f, decomp_state
);
2714 err
= DECR_DATAFORMAT
;
2724 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2727 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2731 if (file
->offset
> CAB(offset
)) {
2732 /* decode bytes and send them to /dev/null */
2733 switch (fdi_decomp(file
, 0, decomp_state
, pszCabPath
, pfnfdin
, pvUser
)) {
2736 case DECR_USERABORT
:
2737 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2740 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2743 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2746 CAB(offset
) = file
->offset
;
2749 /* now do the actual decompression */
2750 err
= fdi_decomp(file
, 1, decomp_state
, pszCabPath
, pfnfdin
, pvUser
);
2751 if (err
) CAB(current
) = NULL
; else CAB(offset
) += file
->length
;
2753 /* fdintCLOSE_FILE_INFO notification */
2754 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2756 fdin
.psz1
= (char *)file
->filename
;
2758 fdin
.cb
= (file
->attribs
& cffile_A_EXEC
) != 0; /* FIXME: is that right? */
2759 fdin
.date
= file
->date
;
2760 fdin
.time
= file
->time
;
2761 fdin
.attribs
= file
->attribs
; /* FIXME: filter _A_EXEC? */
2762 ((*pfnfdin
)(fdintCLOSE_FILE_INFO
, &fdin
));
2768 case DECR_USERABORT
:
2769 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2772 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2775 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2781 if (fol
) free_decompression_temps(fdi
, fol
, decomp_state
);
2782 free_decompression_mem(fdi
, decomp_state
);
2786 bail_and_fail
: /* here we free ram before error returns */
2788 if (fol
) free_decompression_temps(fdi
, fol
, decomp_state
);
2790 if (filehf
) fdi
->close(filehf
);
2792 free_decompression_mem(fdi
, decomp_state
);
2797 /***********************************************************************
2798 * FDIDestroy (CABINET.23)
2800 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2801 * of FDICopy. Only reason for failure would be an invalid handle.
2804 * hfdi [I] The HFDI to free
2810 BOOL __cdecl
FDIDestroy(HFDI hfdi
)
2812 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
2814 TRACE("(hfdi == ^%p)\n", hfdi
);
2815 if (!fdi
) return FALSE
;
2816 fdi
->magic
= 0; /* paranoia */
2821 /***********************************************************************
2822 * FDITruncateCabinet (CABINET.24)
2824 * Removes all folders of a cabinet file after and including the
2825 * specified folder number.
2828 * hfdi [I] Handle to the FDI context.
2829 * pszCabinetName [I] Filename of the cabinet.
2830 * iFolderToDelete [I] Index of the first folder to delete.
2837 * The PFNWRITE function supplied to FDICreate must truncate the
2838 * file at the current position if the number of bytes to write is 0.
2840 BOOL __cdecl
FDITruncateCabinet(
2842 char *pszCabinetName
,
2843 USHORT iFolderToDelete
)
2845 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
2847 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2848 hfdi
, debugstr_a(pszCabinetName
), iFolderToDelete
);
2850 if (!fdi
) return FALSE
;
2852 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);