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;
528 LONG base_offset
, cabsize
;
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
);
536 * FIXME: I just noticed that I am memorizing the initial file pointer
537 * offset and restoring it before reading in the rest of the header
538 * information in the cabinet. Perhaps that's correct -- that is, perhaps
539 * this API is supposed to support "streaming" cabinets which are embedded
540 * in other files, or cabinets which begin at file offsets other than zero.
541 * Otherwise, I should instead go to the absolute beginning of the file.
542 * (Either way, the semantics of wine's FDICopy require me to leave the
543 * file pointer where it is afterwards -- If Windows does not do so, we
544 * ought to duplicate the native behavior in the FDIIsCabinet API, not here.
546 * So, the answer lies in Windows; will native cabinet.dll recognize a
547 * cabinet "file" embedded in another file? Note that cabextract.c does
548 * support this, which implies that Microsoft's might. I haven't tried it
549 * yet so I don't know. ATM, most of wine's FDI cabinet routines (except
550 * this one) would not work in this way. To fix it, we could just make the
551 * various references to absolute file positions in the code relative to an
552 * initial "beginning" offset. Because the FDICopy API doesn't take a
553 * file-handle like this one, we would therein need to search through the
554 * file for the beginning of the cabinet (as we also do in cabextract.c).
555 * Note that this limits us to a maximum of one cabinet per. file: the first.
557 * So, in summary: either the code below is wrong, or the rest of fdi.c is
558 * wrong... I cannot imagine that both are correct ;) One of these flaws
559 * should be fixed after determining the behavior on Windows. We ought
560 * to check both FDIIsCabinet and FDICopy for the right behavior.
565 /* get basic offset & size info */
566 base_offset
= FDI_getoffset(fdi
, hf
);
568 if (fdi
->seek(hf
, 0, SEEK_END
) == -1) {
569 if (pmii
) set_error( fdi
, FDIERROR_NOT_A_CABINET
, 0 );
573 cabsize
= FDI_getoffset(fdi
, hf
);
575 if ((cabsize
== -1) || (base_offset
== -1) ||
576 ( fdi
->seek(hf
, base_offset
, SEEK_SET
) == -1 )) {
577 if (pmii
) set_error( fdi
, FDIERROR_NOT_A_CABINET
, 0 );
581 /* read in the CFHEADER */
582 if (fdi
->read(hf
, buf
, cfhead_SIZEOF
) != cfhead_SIZEOF
) {
583 if (pmii
) set_error( fdi
, FDIERROR_NOT_A_CABINET
, 0 );
587 /* check basic MSCF signature */
588 if (EndGetI32(buf
+cfhead_Signature
) != 0x4643534d) {
589 if (pmii
) set_error( fdi
, FDIERROR_NOT_A_CABINET
, 0 );
593 /* get the number of folders */
594 num_folders
= EndGetI16(buf
+cfhead_NumFolders
);
596 /* get the number of files */
597 num_files
= EndGetI16(buf
+cfhead_NumFiles
);
600 setid
= EndGetI16(buf
+cfhead_SetID
);
602 /* cabinet (set) index */
603 cabidx
= EndGetI16(buf
+cfhead_CabinetIndex
);
605 /* check the header revision */
606 if ((buf
[cfhead_MajorVersion
] > 1) ||
607 (buf
[cfhead_MajorVersion
] == 1 && buf
[cfhead_MinorVersion
] > 3))
609 WARN("cabinet format version > 1.3\n");
610 if (pmii
) set_error( fdi
, FDIERROR_UNKNOWN_CABINET_VERSION
, 0 /* ? */ );
614 /* pull the flags out */
615 flags
= EndGetI16(buf
+cfhead_Flags
);
617 /* read the reserved-sizes part of header, if present */
618 if (flags
& cfheadRESERVE_PRESENT
) {
619 if (fdi
->read(hf
, buf
, cfheadext_SIZEOF
) != cfheadext_SIZEOF
) {
620 ERR("bunk reserve-sizes?\n");
621 if (pmii
) set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 /* ? */ );
625 header_resv
= EndGetI16(buf
+cfheadext_HeaderReserved
);
626 if (pmii
) pmii
->header_resv
= header_resv
;
627 folder_resv
= buf
[cfheadext_FolderReserved
];
628 if (pmii
) pmii
->folder_resv
= folder_resv
;
629 block_resv
= buf
[cfheadext_DataReserved
];
630 if (pmii
) pmii
->block_resv
= block_resv
;
632 if (header_resv
> 60000) {
633 WARN("WARNING; header reserved space > 60000\n");
636 /* skip the reserved header */
637 if ((header_resv
) && (fdi
->seek(hf
, header_resv
, SEEK_CUR
) == -1)) {
638 ERR("seek failure: header_resv\n");
639 if (pmii
) set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 /* ? */ );
644 if (flags
& cfheadPREV_CABINET
) {
645 prevname
= FDI_read_string(fdi
, hf
, cabsize
);
647 if (pmii
) set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 /* ? */ );
651 pmii
->prevname
= prevname
;
654 previnfo
= FDI_read_string(fdi
, hf
, cabsize
);
657 pmii
->previnfo
= previnfo
;
663 if (flags
& cfheadNEXT_CABINET
) {
665 pmii
->hasnext
= TRUE
;
666 nextname
= FDI_read_string(fdi
, hf
, cabsize
);
668 if ((flags
& cfheadPREV_CABINET
) && pmii
) {
669 if (pmii
->prevname
) fdi
->free(prevname
);
670 if (pmii
->previnfo
) fdi
->free(previnfo
);
672 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 /* ? */ );
676 pmii
->nextname
= nextname
;
679 nextinfo
= FDI_read_string(fdi
, hf
, cabsize
);
682 pmii
->nextinfo
= nextinfo
;
688 /* we could process the whole cabinet searching for problems;
689 instead lets stop here. Now let's fill out the paperwork */
690 pfdici
->cbCabinet
= cabsize
;
691 pfdici
->cFolders
= num_folders
;
692 pfdici
->cFiles
= num_files
;
693 pfdici
->setID
= setid
;
694 pfdici
->iCabinet
= cabidx
;
695 pfdici
->fReserve
= (flags
& cfheadRESERVE_PRESENT
) != 0;
696 pfdici
->hasprev
= (flags
& cfheadPREV_CABINET
) != 0;
697 pfdici
->hasnext
= (flags
& cfheadNEXT_CABINET
) != 0;
701 /***********************************************************************
702 * FDIIsCabinet (CABINET.21)
704 * Informs the caller as to whether or not the provided file handle is
705 * really a cabinet or not, filling out the provided PFDICABINETINFO
706 * structure with information about the cabinet. Brief explanations of
707 * the elements of this structure are available as comments accompanying
708 * its definition in wine's include/fdi.h.
711 * hfdi [I] An HFDI from FDICreate
712 * hf [I] The file handle about which the caller inquires
713 * pfdici [IO] Pointer to a PFDICABINETINFO structure which will
714 * be filled out with information about the cabinet
715 * file indicated by hf if, indeed, it is determined
719 * TRUE if the file is a cabinet. The info pointed to by pfdici will
721 * FALSE if the file is not a cabinet, or if an error was encountered
722 * while processing the cabinet. The PERF structure provided to
723 * FDICreate can be queried for more error information.
728 BOOL __cdecl
FDIIsCabinet(HFDI hfdi
, INT_PTR hf
, PFDICABINETINFO pfdici
)
731 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
733 TRACE("(hfdi == ^%p, hf == ^%ld, pfdici == ^%p)\n", hfdi
, hf
, pfdici
);
735 if (!fdi
) return FALSE
;
738 SetLastError(ERROR_INVALID_HANDLE
);
743 SetLastError(ERROR_BAD_ARGUMENTS
);
746 rv
= FDI_read_entries(fdi
, hf
, pfdici
, NULL
);
749 pfdici
->hasnext
= FALSE
; /* yuck. duplicate apparent cabinet.dll bug */
754 /******************************************************************
755 * QTMfdi_initmodel (internal)
757 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
759 static void QTMfdi_initmodel(struct QTMmodel
*m
, struct QTMmodelsym
*sym
, int n
, int s
) {
764 memset(m
->tabloc
, 0xFF, sizeof(m
->tabloc
)); /* clear out look-up table */
765 for (i
= 0; i
< n
; i
++) {
766 m
->tabloc
[i
+s
] = i
; /* set up a look-up entry for symbol */
767 m
->syms
[i
].sym
= i
+s
; /* actual symbol */
768 m
->syms
[i
].cumfreq
= n
-i
; /* current frequency of that symbol */
770 m
->syms
[n
].cumfreq
= 0;
773 /******************************************************************
774 * QTMfdi_init (internal)
776 static int QTMfdi_init(int window
, int level
, fdi_decomp_state
*decomp_state
) {
777 unsigned int wndsize
= 1 << window
;
778 int msz
= window
* 2, i
;
781 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
782 /* if a previously allocated window is big enough, keep it */
783 if (window
< 10 || window
> 21) return DECR_DATAFORMAT
;
784 if (QTM(actual_size
) < wndsize
) {
785 if (QTM(window
)) CAB(fdi
)->free(QTM(window
));
789 if (!(QTM(window
) = CAB(fdi
)->alloc(wndsize
))) return DECR_NOMEMORY
;
790 QTM(actual_size
) = wndsize
;
792 QTM(window_size
) = wndsize
;
793 QTM(window_posn
) = 0;
795 /* initialize static slot/extrabits tables */
796 for (i
= 0, j
= 0; i
< 27; i
++) {
797 CAB(q_length_extra
)[i
] = (i
== 26) ? 0 : (i
< 2 ? 0 : i
- 2) >> 2;
798 CAB(q_length_base
)[i
] = j
; j
+= 1 << ((i
== 26) ? 5 : CAB(q_length_extra
)[i
]);
800 for (i
= 0, j
= 0; i
< 42; i
++) {
801 CAB(q_extra_bits
)[i
] = (i
< 2 ? 0 : i
-2) >> 1;
802 CAB(q_position_base
)[i
] = j
; j
+= 1 << CAB(q_extra_bits
)[i
];
805 /* initialize arithmetic coding models */
807 QTMfdi_initmodel(&QTM(model7
), QTM(m7sym
), 7, 0);
809 QTMfdi_initmodel(&QTM(model00
), QTM(m00sym
), 0x40, 0x00);
810 QTMfdi_initmodel(&QTM(model40
), QTM(m40sym
), 0x40, 0x40);
811 QTMfdi_initmodel(&QTM(model80
), QTM(m80sym
), 0x40, 0x80);
812 QTMfdi_initmodel(&QTM(modelC0
), QTM(mC0sym
), 0x40, 0xC0);
814 /* model 4 depends on table size, ranges from 20 to 24 */
815 QTMfdi_initmodel(&QTM(model4
), QTM(m4sym
), (msz
< 24) ? msz
: 24, 0);
816 /* model 5 depends on table size, ranges from 20 to 36 */
817 QTMfdi_initmodel(&QTM(model5
), QTM(m5sym
), (msz
< 36) ? msz
: 36, 0);
818 /* model 6pos depends on table size, ranges from 20 to 42 */
819 QTMfdi_initmodel(&QTM(model6pos
), QTM(m6psym
), msz
, 0);
820 QTMfdi_initmodel(&QTM(model6len
), QTM(m6lsym
), 27, 0);
825 /************************************************************
826 * LZXfdi_init (internal)
828 static int LZXfdi_init(int window
, fdi_decomp_state
*decomp_state
) {
829 static const cab_UBYTE bits
[] =
830 { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
831 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
832 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
834 static const cab_ULONG base
[] =
835 { 0, 1, 2, 3, 4, 6, 8, 12,
836 16, 24, 32, 48, 64, 96, 128, 192,
837 256, 384, 512, 768, 1024, 1536, 2048, 3072,
838 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
839 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
840 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
841 1835008, 1966080, 2097152};
842 cab_ULONG wndsize
= 1 << window
;
845 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
846 /* if a previously allocated window is big enough, keep it */
847 if (window
< 15 || window
> 21) return DECR_DATAFORMAT
;
848 if (LZX(actual_size
) < wndsize
) {
849 if (LZX(window
)) CAB(fdi
)->free(LZX(window
));
853 if (!(LZX(window
) = CAB(fdi
)->alloc(wndsize
))) return DECR_NOMEMORY
;
854 LZX(actual_size
) = wndsize
;
856 LZX(window_size
) = wndsize
;
858 /* initialize static tables */
859 memcpy(CAB(extra_bits
), bits
, sizeof(bits
));
860 memcpy(CAB(lzx_position_base
), base
, sizeof(base
));
862 /* calculate required position slots */
863 if (window
== 20) posn_slots
= 42;
864 else if (window
== 21) posn_slots
= 50;
865 else posn_slots
= window
<< 1;
867 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
869 LZX(R0
) = LZX(R1
) = LZX(R2
) = 1;
870 LZX(main_elements
) = LZX_NUM_CHARS
+ (posn_slots
<< 3);
871 LZX(header_read
) = 0;
872 LZX(frames_read
) = 0;
873 LZX(block_remaining
) = 0;
874 LZX(block_type
) = LZX_BLOCKTYPE_INVALID
;
875 LZX(intel_curpos
) = 0;
876 LZX(intel_started
) = 0;
877 LZX(window_posn
) = 0;
879 /* initialize tables to 0 (because deltas will be applied to them) */
880 memset(LZX(MAINTREE_len
), 0, sizeof(LZX(MAINTREE_len
)));
881 memset(LZX(LENGTH_len
), 0, sizeof(LZX(LENGTH_len
)));
886 /****************************************************
887 * NONEfdi_decomp(internal)
889 static int NONEfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
891 if (inlen
!= outlen
) return DECR_ILLEGALDATA
;
892 if (outlen
> CAB_BLOCKMAX
) return DECR_DATAFORMAT
;
893 memcpy(CAB(outbuf
), CAB(inbuf
), (size_t) inlen
);
897 /********************************************************
898 * Ziphuft_free (internal)
900 static void fdi_Ziphuft_free(FDI_Int
*fdi
, struct Ziphuft
*t
)
902 register struct Ziphuft
*p
, *q
;
904 /* Go through linked list, freeing from the allocated (t[-1]) address. */
914 /*********************************************************
915 * fdi_Ziphuft_build (internal)
917 static cab_LONG
fdi_Ziphuft_build(cab_ULONG
*b
, cab_ULONG n
, cab_ULONG s
, const cab_UWORD
*d
, const cab_UWORD
*e
,
918 struct Ziphuft
**t
, cab_LONG
*m
, fdi_decomp_state
*decomp_state
)
920 cab_ULONG a
; /* counter for codes of length k */
921 cab_ULONG el
; /* length of EOB code (value 256) */
922 cab_ULONG f
; /* i repeats in table every f entries */
923 cab_LONG g
; /* maximum code length */
924 cab_LONG h
; /* table level */
925 register cab_ULONG i
; /* counter, current code */
926 register cab_ULONG j
; /* counter */
927 register cab_LONG k
; /* number of bits in current code */
928 cab_LONG
*l
; /* stack of bits per table */
929 register cab_ULONG
*p
; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
930 register struct Ziphuft
*q
; /* points to current table */
931 struct Ziphuft r
; /* table entry for structure assignment */
932 register cab_LONG w
; /* bits before this table == (l * h) */
933 cab_ULONG
*xp
; /* pointer into x */
934 cab_LONG y
; /* number of dummy codes added */
935 cab_ULONG z
; /* number of entries in current table */
939 /* Generate counts for each bit length */
940 el
= n
> 256 ? b
[256] : ZIPBMAX
; /* set length of EOB code, if any */
942 for(i
= 0; i
< ZIPBMAX
+1; ++i
)
947 ZIP(c
)[*p
]++; p
++; /* assume all entries <= ZIPBMAX */
949 if (ZIP(c
)[0] == n
) /* null input--all zero length codes */
956 /* Find minimum and maximum length, bound *m by those */
957 for (j
= 1; j
<= ZIPBMAX
; j
++)
960 k
= j
; /* minimum code length */
961 if ((cab_ULONG
)*m
< j
)
963 for (i
= ZIPBMAX
; i
; i
--)
966 g
= i
; /* maximum code length */
967 if ((cab_ULONG
)*m
> i
)
970 /* Adjust last length count to fill out codes, if needed */
971 for (y
= 1 << j
; j
< i
; j
++, y
<<= 1)
972 if ((y
-= ZIP(c
)[j
]) < 0)
973 return 2; /* bad input: more codes than bits */
974 if ((y
-= ZIP(c
)[i
]) < 0)
978 /* Generate starting offsets LONGo the value table for each length */
980 p
= ZIP(c
) + 1; xp
= ZIP(x
) + 2;
982 { /* note that i == g from above */
986 /* Make a table of values in order of bit lengths */
990 ZIP(v
)[ZIP(x
)[j
]++] = i
;
994 /* Generate the Huffman codes and for each, make the table entries */
995 ZIP(x
)[0] = i
= 0; /* first Huffman code is zero */
996 p
= ZIP(v
); /* grab values in bit order */
997 h
= -1; /* no tables yet--level -1 */
998 w
= l
[-1] = 0; /* no bits decoded yet */
999 ZIP(u
)[0] = NULL
; /* just to keep compilers happy */
1000 q
= NULL
; /* ditto */
1003 /* go through the bit lengths (k already is bits in shortest code) */
1009 /* here i is the Huffman code of length k bits for value *p */
1010 /* make tables up to required level */
1011 while (k
> w
+ l
[h
])
1013 w
+= l
[h
++]; /* add bits already decoded */
1015 /* compute minimum size table less than or equal to *m bits */
1016 if ((z
= g
- w
) > (cab_ULONG
)*m
) /* upper limit */
1018 if ((f
= 1 << (j
= k
- w
)) > a
+ 1) /* try a k-w bit table */
1019 { /* too few codes for k-w bit table */
1020 f
-= a
+ 1; /* deduct codes from patterns left */
1022 while (++j
< z
) /* try smaller tables up to z bits */
1024 if ((f
<<= 1) <= *++xp
)
1025 break; /* enough codes to use up j bits */
1026 f
-= *xp
; /* else deduct codes from patterns */
1029 if ((cab_ULONG
)w
+ j
> el
&& (cab_ULONG
)w
< el
)
1030 j
= el
- w
; /* make EOB code end at table */
1031 z
= 1 << j
; /* table entries for j-bit table */
1032 l
[h
] = j
; /* set table size in stack */
1034 /* allocate and link in new table */
1035 if (!(q
= CAB(fdi
)->alloc((z
+ 1)*sizeof(struct Ziphuft
))))
1038 fdi_Ziphuft_free(CAB(fdi
), ZIP(u
)[0]);
1039 return 3; /* not enough memory */
1041 *t
= q
+ 1; /* link to list for Ziphuft_free() */
1042 *(t
= &(q
->v
.t
)) = NULL
;
1043 ZIP(u
)[h
] = ++q
; /* table starts after link */
1045 /* connect to last table, if there is one */
1048 ZIP(x
)[h
] = i
; /* save pattern for backing up */
1049 r
.b
= (cab_UBYTE
)l
[h
-1]; /* bits to dump before this table */
1050 r
.e
= (cab_UBYTE
)(16 + j
); /* bits in this table */
1051 r
.v
.t
= q
; /* pointer to this table */
1052 j
= (i
& ((1 << w
) - 1)) >> (w
- l
[h
-1]);
1053 ZIP(u
)[h
-1][j
] = r
; /* connect to last table */
1057 /* set up table entry in r */
1058 r
.b
= (cab_UBYTE
)(k
- w
);
1059 if (p
>= ZIP(v
) + n
)
1060 r
.e
= 99; /* out of values--invalid code */
1063 r
.e
= (cab_UBYTE
)(*p
< 256 ? 16 : 15); /* 256 is end-of-block code */
1064 r
.v
.n
= *p
++; /* simple code is just the value */
1068 r
.e
= (cab_UBYTE
)e
[*p
- s
]; /* non-simple--look up in lists */
1069 r
.v
.n
= d
[*p
++ - s
];
1072 /* fill code-like entries with r */
1074 for (j
= i
>> w
; j
< z
; j
+= f
)
1077 /* backwards increment the k-bit code i */
1078 for (j
= 1 << (k
- 1); i
& j
; j
>>= 1)
1082 /* backup over finished tables */
1083 while ((i
& ((1 << w
) - 1)) != ZIP(x
)[h
])
1084 w
-= l
[--h
]; /* don't need to update q */
1088 /* return actual size of base table */
1091 /* Return true (1) if we were given an incomplete table */
1092 return y
!= 0 && g
!= 1;
1095 /*********************************************************
1096 * fdi_Zipinflate_codes (internal)
1098 static cab_LONG
fdi_Zipinflate_codes(const struct Ziphuft
*tl
, const struct Ziphuft
*td
,
1099 cab_LONG bl
, cab_LONG bd
, fdi_decomp_state
*decomp_state
)
1101 register cab_ULONG e
; /* table entry flag/number of extra bits */
1102 cab_ULONG n
, d
; /* length and index for copy */
1103 cab_ULONG w
; /* current window position */
1104 const struct Ziphuft
*t
; /* pointer to table entry */
1105 cab_ULONG ml
, md
; /* masks for bl and bd bits */
1106 register cab_ULONG b
; /* bit buffer */
1107 register cab_ULONG k
; /* number of bits in bit buffer */
1109 /* make local copies of globals */
1110 b
= ZIP(bb
); /* initialize bit buffer */
1112 w
= ZIP(window_posn
); /* initialize window position */
1114 /* inflate the coded data */
1115 ml
= Zipmask
[bl
]; /* precompute masks for speed */
1120 ZIPNEEDBITS((cab_ULONG
)bl
)
1121 if((e
= (t
= tl
+ (b
& ml
))->e
) > 16)
1129 } while ((e
= (t
= t
->v
.t
+ (b
& Zipmask
[e
]))->e
) > 16);
1131 if (e
== 16) /* then it's a literal */
1132 CAB(outbuf
)[w
++] = (cab_UBYTE
)t
->v
.n
;
1133 else /* it's an EOB or a length */
1135 /* exit if end of block */
1139 /* get length of block to copy */
1141 n
= t
->v
.n
+ (b
& Zipmask
[e
]);
1144 /* decode distance of block to copy */
1145 ZIPNEEDBITS((cab_ULONG
)bd
)
1146 if ((e
= (t
= td
+ (b
& md
))->e
) > 16)
1153 } while ((e
= (t
= t
->v
.t
+ (b
& Zipmask
[e
]))->e
) > 16);
1156 d
= w
- t
->v
.n
- (b
& Zipmask
[e
]);
1161 e
= ZIPWSIZE
- max(d
, w
);
1166 CAB(outbuf
)[w
++] = CAB(outbuf
)[d
++];
1172 /* restore the globals from the locals */
1173 ZIP(window_posn
) = w
; /* restore global window pointer */
1174 ZIP(bb
) = b
; /* restore global bit buffer */
1181 /***********************************************************
1182 * Zipinflate_stored (internal)
1184 static cab_LONG
fdi_Zipinflate_stored(fdi_decomp_state
*decomp_state
)
1185 /* "decompress" an inflated type 0 (stored) block. */
1187 cab_ULONG n
; /* number of bytes in block */
1188 cab_ULONG w
; /* current window position */
1189 register cab_ULONG b
; /* bit buffer */
1190 register cab_ULONG k
; /* number of bits in bit buffer */
1192 /* make local copies of globals */
1193 b
= ZIP(bb
); /* initialize bit buffer */
1195 w
= ZIP(window_posn
); /* initialize window position */
1197 /* go to byte boundary */
1201 /* get the length and its complement */
1206 if (n
!= ((~b
) & 0xffff))
1207 return 1; /* error in compressed data */
1210 /* read and output the compressed data */
1214 CAB(outbuf
)[w
++] = (cab_UBYTE
)b
;
1218 /* restore the globals from the locals */
1219 ZIP(window_posn
) = w
; /* restore global window pointer */
1220 ZIP(bb
) = b
; /* restore global bit buffer */
1225 /******************************************************
1226 * fdi_Zipinflate_fixed (internal)
1228 static cab_LONG
fdi_Zipinflate_fixed(fdi_decomp_state
*decomp_state
)
1230 struct Ziphuft
*fixed_tl
;
1231 struct Ziphuft
*fixed_td
;
1232 cab_LONG fixed_bl
, fixed_bd
;
1233 cab_LONG i
; /* temporary variable */
1239 for(i
= 0; i
< 144; i
++)
1245 for(; i
< 288; i
++) /* make a complete, but wrong code set */
1248 if((i
= fdi_Ziphuft_build(l
, 288, 257, Zipcplens
, Zipcplext
, &fixed_tl
, &fixed_bl
, decomp_state
)))
1251 /* distance table */
1252 for(i
= 0; i
< 30; i
++) /* make an incomplete code set */
1255 if((i
= fdi_Ziphuft_build(l
, 30, 0, Zipcpdist
, Zipcpdext
, &fixed_td
, &fixed_bd
, decomp_state
)) > 1)
1257 fdi_Ziphuft_free(CAB(fdi
), fixed_tl
);
1261 /* decompress until an end-of-block code */
1262 i
= fdi_Zipinflate_codes(fixed_tl
, fixed_td
, fixed_bl
, fixed_bd
, decomp_state
);
1264 fdi_Ziphuft_free(CAB(fdi
), fixed_td
);
1265 fdi_Ziphuft_free(CAB(fdi
), fixed_tl
);
1269 /**************************************************************
1270 * fdi_Zipinflate_dynamic (internal)
1272 static cab_LONG
fdi_Zipinflate_dynamic(fdi_decomp_state
*decomp_state
)
1273 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1275 cab_LONG i
; /* temporary variables */
1278 cab_ULONG l
; /* last length */
1279 cab_ULONG m
; /* mask for bit lengths table */
1280 cab_ULONG n
; /* number of lengths to get */
1281 struct Ziphuft
*tl
; /* literal/length code table */
1282 struct Ziphuft
*td
; /* distance code table */
1283 cab_LONG bl
; /* lookup bits for tl */
1284 cab_LONG bd
; /* lookup bits for td */
1285 cab_ULONG nb
; /* number of bit length codes */
1286 cab_ULONG nl
; /* number of literal/length codes */
1287 cab_ULONG nd
; /* number of distance codes */
1288 register cab_ULONG b
; /* bit buffer */
1289 register cab_ULONG k
; /* number of bits in bit buffer */
1291 /* make local bit buffer */
1296 /* read in table lengths */
1298 nl
= 257 + (b
& 0x1f); /* number of literal/length codes */
1301 nd
= 1 + (b
& 0x1f); /* number of distance codes */
1304 nb
= 4 + (b
& 0xf); /* number of bit length codes */
1306 if(nl
> 288 || nd
> 32)
1307 return 1; /* bad lengths */
1309 /* read in bit-length-code lengths */
1310 for(j
= 0; j
< nb
; j
++)
1313 ll
[Zipborder
[j
]] = b
& 7;
1317 ll
[Zipborder
[j
]] = 0;
1319 /* build decoding table for trees--single level, 7 bit lookup */
1321 if((i
= fdi_Ziphuft_build(ll
, 19, 19, NULL
, NULL
, &tl
, &bl
, decomp_state
)) != 0)
1324 fdi_Ziphuft_free(CAB(fdi
), tl
);
1325 return i
; /* incomplete code set */
1328 /* read in literal and distance code lengths */
1332 while((cab_ULONG
)i
< n
)
1334 ZIPNEEDBITS((cab_ULONG
)bl
)
1335 j
= (td
= tl
+ (b
& m
))->b
;
1338 if (j
< 16) /* length of code in bits (0..15) */
1339 ll
[i
++] = l
= j
; /* save last length in l */
1340 else if (j
== 16) /* repeat last length 3 to 6 times */
1345 if((cab_ULONG
)i
+ j
> n
)
1350 else if (j
== 17) /* 3 to 10 zero length codes */
1355 if ((cab_ULONG
)i
+ j
> n
)
1361 else /* j == 18: 11 to 138 zero length codes */
1364 j
= 11 + (b
& 0x7f);
1366 if ((cab_ULONG
)i
+ j
> n
)
1374 /* free decoding table for trees */
1375 fdi_Ziphuft_free(CAB(fdi
), tl
);
1377 /* restore the global bit buffer */
1381 /* build the decoding tables for literal/length and distance codes */
1383 if((i
= fdi_Ziphuft_build(ll
, nl
, 257, Zipcplens
, Zipcplext
, &tl
, &bl
, decomp_state
)) != 0)
1386 fdi_Ziphuft_free(CAB(fdi
), tl
);
1387 return i
; /* incomplete code set */
1390 fdi_Ziphuft_build(ll
+ nl
, nd
, 0, Zipcpdist
, Zipcpdext
, &td
, &bd
, decomp_state
);
1392 /* decompress until an end-of-block code */
1393 if(fdi_Zipinflate_codes(tl
, td
, bl
, bd
, decomp_state
))
1396 /* free the decoding tables, return */
1397 fdi_Ziphuft_free(CAB(fdi
), tl
);
1398 fdi_Ziphuft_free(CAB(fdi
), td
);
1402 /*****************************************************
1403 * fdi_Zipinflate_block (internal)
1405 static cab_LONG
fdi_Zipinflate_block(cab_LONG
*e
, fdi_decomp_state
*decomp_state
) /* e == last block flag */
1406 { /* decompress an inflated block */
1407 cab_ULONG t
; /* block type */
1408 register cab_ULONG b
; /* bit buffer */
1409 register cab_ULONG k
; /* number of bits in bit buffer */
1411 /* make local bit buffer */
1415 /* read in last block bit */
1417 *e
= (cab_LONG
)b
& 1;
1420 /* read in block type */
1425 /* restore the global bit buffer */
1429 /* inflate that block type */
1431 return fdi_Zipinflate_dynamic(decomp_state
);
1433 return fdi_Zipinflate_stored(decomp_state
);
1435 return fdi_Zipinflate_fixed(decomp_state
);
1436 /* bad block type */
1440 /****************************************************
1441 * ZIPfdi_decomp(internal)
1443 static int ZIPfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
1445 cab_LONG e
; /* last block flag */
1447 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1449 ZIP(inpos
) = CAB(inbuf
);
1450 ZIP(bb
) = ZIP(bk
) = ZIP(window_posn
) = 0;
1451 if(outlen
> ZIPWSIZE
)
1452 return DECR_DATAFORMAT
;
1454 /* CK = Chris Kirmse, official Microsoft purloiner */
1455 if(ZIP(inpos
)[0] != 0x43 || ZIP(inpos
)[1] != 0x4B)
1456 return DECR_ILLEGALDATA
;
1460 if(fdi_Zipinflate_block(&e
, decomp_state
))
1461 return DECR_ILLEGALDATA
;
1464 /* return success */
1468 /*******************************************************************
1469 * QTMfdi_decomp(internal)
1471 static int QTMfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
1473 cab_UBYTE
*inpos
= CAB(inbuf
);
1474 cab_UBYTE
*window
= QTM(window
);
1475 cab_UBYTE
*runsrc
, *rundest
;
1476 cab_ULONG window_posn
= QTM(window_posn
);
1477 cab_ULONG window_size
= QTM(window_size
);
1479 /* used by bitstream macros */
1480 register int bitsleft
, bitrun
, bitsneed
;
1481 register cab_ULONG bitbuf
;
1483 /* used by GET_SYMBOL */
1488 int extra
, togo
= outlen
, match_length
= 0, copy_length
;
1489 cab_UBYTE selector
, sym
;
1490 cab_ULONG match_offset
= 0;
1492 cab_UWORD H
= 0xFFFF, L
= 0, C
;
1494 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1496 /* read initial value of C */
1500 /* apply 2^x-1 mask */
1501 window_posn
&= window_size
- 1;
1502 /* runs can't straddle the window wraparound */
1503 if ((window_posn
+ togo
) > window_size
) {
1504 TRACE("straddled run\n");
1505 return DECR_DATAFORMAT
;
1509 GET_SYMBOL(model7
, selector
);
1512 GET_SYMBOL(model00
, sym
); window
[window_posn
++] = sym
; togo
--;
1515 GET_SYMBOL(model40
, sym
); window
[window_posn
++] = sym
; togo
--;
1518 GET_SYMBOL(model80
, sym
); window
[window_posn
++] = sym
; togo
--;
1521 GET_SYMBOL(modelC0
, sym
); window
[window_posn
++] = sym
; togo
--;
1525 /* selector 4 = fixed length of 3 */
1526 GET_SYMBOL(model4
, sym
);
1527 Q_READ_BITS(extra
, CAB(q_extra_bits
)[sym
]);
1528 match_offset
= CAB(q_position_base
)[sym
] + extra
+ 1;
1533 /* selector 5 = fixed length of 4 */
1534 GET_SYMBOL(model5
, sym
);
1535 Q_READ_BITS(extra
, CAB(q_extra_bits
)[sym
]);
1536 match_offset
= CAB(q_position_base
)[sym
] + extra
+ 1;
1541 /* selector 6 = variable length */
1542 GET_SYMBOL(model6len
, sym
);
1543 Q_READ_BITS(extra
, CAB(q_length_extra
)[sym
]);
1544 match_length
= CAB(q_length_base
)[sym
] + extra
+ 5;
1545 GET_SYMBOL(model6pos
, sym
);
1546 Q_READ_BITS(extra
, CAB(q_extra_bits
)[sym
]);
1547 match_offset
= CAB(q_position_base
)[sym
] + extra
+ 1;
1551 TRACE("Selector is bogus\n");
1552 return DECR_ILLEGALDATA
;
1555 /* if this is a match */
1556 if (selector
>= 4) {
1557 rundest
= window
+ window_posn
;
1558 togo
-= match_length
;
1560 /* copy any wrapped around source data */
1561 if (window_posn
>= match_offset
) {
1563 runsrc
= rundest
- match_offset
;
1565 runsrc
= rundest
+ (window_size
- match_offset
);
1566 copy_length
= match_offset
- window_posn
;
1567 if (copy_length
< match_length
) {
1568 match_length
-= copy_length
;
1569 window_posn
+= copy_length
;
1570 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1574 window_posn
+= match_length
;
1576 /* copy match data - no worries about destination wraps */
1577 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1579 } /* while (togo > 0) */
1582 TRACE("Frame overflow, this_run = %d\n", togo
);
1583 return DECR_ILLEGALDATA
;
1586 memcpy(CAB(outbuf
), window
+ ((!window_posn
) ? window_size
: window_posn
) -
1589 QTM(window_posn
) = window_posn
;
1593 /************************************************************
1594 * fdi_lzx_read_lens (internal)
1596 static int fdi_lzx_read_lens(cab_UBYTE
*lens
, cab_ULONG first
, cab_ULONG last
, struct lzx_bits
*lb
,
1597 fdi_decomp_state
*decomp_state
) {
1601 register cab_ULONG bitbuf
= lb
->bb
;
1602 register int bitsleft
= lb
->bl
;
1603 cab_UBYTE
*inpos
= lb
->ip
;
1606 for (x
= 0; x
< 20; x
++) {
1608 LENTABLE(PRETREE
)[x
] = y
;
1610 BUILD_TABLE(PRETREE
);
1612 for (x
= first
; x
< last
; ) {
1613 READ_HUFFSYM(PRETREE
, z
);
1615 READ_BITS(y
, 4); y
+= 4;
1616 while (y
--) lens
[x
++] = 0;
1619 READ_BITS(y
, 5); y
+= 20;
1620 while (y
--) lens
[x
++] = 0;
1623 READ_BITS(y
, 1); y
+= 4;
1624 READ_HUFFSYM(PRETREE
, z
);
1625 z
= lens
[x
] - z
; if (z
< 0) z
+= 17;
1626 while (y
--) lens
[x
++] = z
;
1629 z
= lens
[x
] - z
; if (z
< 0) z
+= 17;
1640 /*******************************************************
1641 * LZXfdi_decomp(internal)
1643 static int LZXfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
) {
1644 cab_UBYTE
*inpos
= CAB(inbuf
);
1645 const cab_UBYTE
*endinp
= inpos
+ inlen
;
1646 cab_UBYTE
*window
= LZX(window
);
1647 cab_UBYTE
*runsrc
, *rundest
;
1648 cab_UWORD
*hufftbl
; /* used in READ_HUFFSYM macro as chosen decoding table */
1650 cab_ULONG window_posn
= LZX(window_posn
);
1651 cab_ULONG window_size
= LZX(window_size
);
1652 cab_ULONG R0
= LZX(R0
);
1653 cab_ULONG R1
= LZX(R1
);
1654 cab_ULONG R2
= LZX(R2
);
1656 register cab_ULONG bitbuf
;
1657 register int bitsleft
;
1658 cab_ULONG match_offset
, i
,j
,k
; /* ijk used in READ_HUFFSYM macro */
1659 struct lzx_bits lb
; /* used in READ_LENGTHS macro */
1661 int togo
= outlen
, this_run
, main_element
, aligned_bits
;
1662 int match_length
, copy_length
, length_footer
, extra
, verbatim_bits
;
1664 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1668 /* read header if necessary */
1669 if (!LZX(header_read
)) {
1671 READ_BITS(k
, 1); if (k
) { READ_BITS(i
,16); READ_BITS(j
,16); }
1672 LZX(intel_filesize
) = (i
<< 16) | j
; /* or 0 if not encoded */
1673 LZX(header_read
) = 1;
1676 /* main decoding loop */
1678 /* last block finished, new block expected */
1679 if (LZX(block_remaining
) == 0) {
1680 if (LZX(block_type
) == LZX_BLOCKTYPE_UNCOMPRESSED
) {
1681 if (LZX(block_length
) & 1) inpos
++; /* realign bitstream to word */
1685 READ_BITS(LZX(block_type
), 3);
1688 LZX(block_remaining
) = LZX(block_length
) = (i
<< 8) | j
;
1690 switch (LZX(block_type
)) {
1691 case LZX_BLOCKTYPE_ALIGNED
:
1692 for (i
= 0; i
< 8; i
++) { READ_BITS(j
, 3); LENTABLE(ALIGNED
)[i
] = j
; }
1693 BUILD_TABLE(ALIGNED
);
1694 /* rest of aligned header is same as verbatim */
1696 case LZX_BLOCKTYPE_VERBATIM
:
1697 READ_LENGTHS(MAINTREE
, 0, 256, fdi_lzx_read_lens
);
1698 READ_LENGTHS(MAINTREE
, 256, LZX(main_elements
), fdi_lzx_read_lens
);
1699 BUILD_TABLE(MAINTREE
);
1700 if (LENTABLE(MAINTREE
)[0xE8] != 0) LZX(intel_started
) = 1;
1702 READ_LENGTHS(LENGTH
, 0, LZX_NUM_SECONDARY_LENGTHS
, fdi_lzx_read_lens
);
1703 BUILD_TABLE(LENGTH
);
1706 case LZX_BLOCKTYPE_UNCOMPRESSED
:
1707 LZX(intel_started
) = 1; /* because we can't assume otherwise */
1708 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1709 if (bitsleft
> 16) inpos
-= 2; /* and align the bitstream! */
1710 R0
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1711 R1
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1712 R2
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1716 return DECR_ILLEGALDATA
;
1720 /* buffer exhaustion check */
1721 if (inpos
> endinp
) {
1722 /* it's possible to have a file where the next run is less than
1723 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1724 * in building the tables will exhaust the buffer, so we should
1725 * allow for this, but not allow those accidentally read bits to
1726 * be used (so we check that there are at least 16 bits
1727 * remaining - in this boundary case they aren't really part of
1728 * the compressed data)
1730 if (inpos
> (endinp
+2) || bitsleft
< 16) return DECR_ILLEGALDATA
;
1733 while ((this_run
= LZX(block_remaining
)) > 0 && togo
> 0) {
1734 if (this_run
> togo
) this_run
= togo
;
1736 LZX(block_remaining
) -= this_run
;
1738 /* apply 2^x-1 mask */
1739 window_posn
&= window_size
- 1;
1740 /* runs can't straddle the window wraparound */
1741 if ((window_posn
+ this_run
) > window_size
)
1742 return DECR_DATAFORMAT
;
1744 switch (LZX(block_type
)) {
1746 case LZX_BLOCKTYPE_VERBATIM
:
1747 while (this_run
> 0) {
1748 READ_HUFFSYM(MAINTREE
, main_element
);
1750 if (main_element
< LZX_NUM_CHARS
) {
1751 /* literal: 0 to LZX_NUM_CHARS-1 */
1752 window
[window_posn
++] = main_element
;
1756 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1757 main_element
-= LZX_NUM_CHARS
;
1759 match_length
= main_element
& LZX_NUM_PRIMARY_LENGTHS
;
1760 if (match_length
== LZX_NUM_PRIMARY_LENGTHS
) {
1761 READ_HUFFSYM(LENGTH
, length_footer
);
1762 match_length
+= length_footer
;
1764 match_length
+= LZX_MIN_MATCH
;
1766 match_offset
= main_element
>> 3;
1768 if (match_offset
> 2) {
1769 /* not repeated offset */
1770 if (match_offset
!= 3) {
1771 extra
= CAB(extra_bits
)[match_offset
];
1772 READ_BITS(verbatim_bits
, extra
);
1773 match_offset
= CAB(lzx_position_base
)[match_offset
]
1774 - 2 + verbatim_bits
;
1780 /* update repeated offset LRU queue */
1781 R2
= R1
; R1
= R0
; R0
= match_offset
;
1783 else if (match_offset
== 0) {
1786 else if (match_offset
== 1) {
1788 R1
= R0
; R0
= match_offset
;
1790 else /* match_offset == 2 */ {
1792 R2
= R0
; R0
= match_offset
;
1795 rundest
= window
+ window_posn
;
1796 this_run
-= match_length
;
1798 /* copy any wrapped around source data */
1799 if (window_posn
>= match_offset
) {
1801 runsrc
= rundest
- match_offset
;
1803 runsrc
= rundest
+ (window_size
- match_offset
);
1804 copy_length
= match_offset
- window_posn
;
1805 if (copy_length
< match_length
) {
1806 match_length
-= copy_length
;
1807 window_posn
+= copy_length
;
1808 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1812 window_posn
+= match_length
;
1814 /* copy match data - no worries about destination wraps */
1815 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1820 case LZX_BLOCKTYPE_ALIGNED
:
1821 while (this_run
> 0) {
1822 READ_HUFFSYM(MAINTREE
, main_element
);
1824 if (main_element
< LZX_NUM_CHARS
) {
1825 /* literal: 0 to LZX_NUM_CHARS-1 */
1826 window
[window_posn
++] = main_element
;
1830 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1831 main_element
-= LZX_NUM_CHARS
;
1833 match_length
= main_element
& LZX_NUM_PRIMARY_LENGTHS
;
1834 if (match_length
== LZX_NUM_PRIMARY_LENGTHS
) {
1835 READ_HUFFSYM(LENGTH
, length_footer
);
1836 match_length
+= length_footer
;
1838 match_length
+= LZX_MIN_MATCH
;
1840 match_offset
= main_element
>> 3;
1842 if (match_offset
> 2) {
1843 /* not repeated offset */
1844 extra
= CAB(extra_bits
)[match_offset
];
1845 match_offset
= CAB(lzx_position_base
)[match_offset
] - 2;
1847 /* verbatim and aligned bits */
1849 READ_BITS(verbatim_bits
, extra
);
1850 match_offset
+= (verbatim_bits
<< 3);
1851 READ_HUFFSYM(ALIGNED
, aligned_bits
);
1852 match_offset
+= aligned_bits
;
1854 else if (extra
== 3) {
1855 /* aligned bits only */
1856 READ_HUFFSYM(ALIGNED
, aligned_bits
);
1857 match_offset
+= aligned_bits
;
1859 else if (extra
> 0) { /* extra==1, extra==2 */
1860 /* verbatim bits only */
1861 READ_BITS(verbatim_bits
, extra
);
1862 match_offset
+= verbatim_bits
;
1864 else /* extra == 0 */ {
1869 /* update repeated offset LRU queue */
1870 R2
= R1
; R1
= R0
; R0
= match_offset
;
1872 else if (match_offset
== 0) {
1875 else if (match_offset
== 1) {
1877 R1
= R0
; R0
= match_offset
;
1879 else /* match_offset == 2 */ {
1881 R2
= R0
; R0
= match_offset
;
1884 rundest
= window
+ window_posn
;
1885 this_run
-= match_length
;
1887 /* copy any wrapped around source data */
1888 if (window_posn
>= match_offset
) {
1890 runsrc
= rundest
- match_offset
;
1892 runsrc
= rundest
+ (window_size
- match_offset
);
1893 copy_length
= match_offset
- window_posn
;
1894 if (copy_length
< match_length
) {
1895 match_length
-= copy_length
;
1896 window_posn
+= copy_length
;
1897 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1901 window_posn
+= match_length
;
1903 /* copy match data - no worries about destination wraps */
1904 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1909 case LZX_BLOCKTYPE_UNCOMPRESSED
:
1910 if ((inpos
+ this_run
) > endinp
) return DECR_ILLEGALDATA
;
1911 memcpy(window
+ window_posn
, inpos
, (size_t) this_run
);
1912 inpos
+= this_run
; window_posn
+= this_run
;
1916 return DECR_ILLEGALDATA
; /* might as well */
1922 if (togo
!= 0) return DECR_ILLEGALDATA
;
1923 memcpy(CAB(outbuf
), window
+ ((!window_posn
) ? window_size
: window_posn
) -
1924 outlen
, (size_t) outlen
);
1926 LZX(window_posn
) = window_posn
;
1931 /* intel E8 decoding */
1932 if ((LZX(frames_read
)++ < 32768) && LZX(intel_filesize
) != 0) {
1933 if (outlen
<= 6 || !LZX(intel_started
)) {
1934 LZX(intel_curpos
) += outlen
;
1937 cab_UBYTE
*data
= CAB(outbuf
);
1938 cab_UBYTE
*dataend
= data
+ outlen
- 10;
1939 cab_LONG curpos
= LZX(intel_curpos
);
1940 cab_LONG filesize
= LZX(intel_filesize
);
1941 cab_LONG abs_off
, rel_off
;
1943 LZX(intel_curpos
) = curpos
+ outlen
;
1945 while (data
< dataend
) {
1946 if (*data
++ != 0xE8) { curpos
++; continue; }
1947 abs_off
= data
[0] | (data
[1]<<8) | (data
[2]<<16) | (data
[3]<<24);
1948 if ((abs_off
>= -curpos
) && (abs_off
< filesize
)) {
1949 rel_off
= (abs_off
>= 0) ? abs_off
- curpos
: abs_off
+ filesize
;
1950 data
[0] = (cab_UBYTE
) rel_off
;
1951 data
[1] = (cab_UBYTE
) (rel_off
>> 8);
1952 data
[2] = (cab_UBYTE
) (rel_off
>> 16);
1953 data
[3] = (cab_UBYTE
) (rel_off
>> 24);
1963 /**********************************************************
1964 * fdi_decomp (internal)
1966 * Decompress the requested number of bytes. If savemode is zero,
1967 * do not save the output anywhere, just plow through blocks until we
1968 * reach the specified (uncompressed) distance from the starting point,
1969 * and remember the position of the cabfile pointer (and which cabfile)
1970 * after we are done; otherwise, save the data out to CAB(filehf),
1971 * decompressing the requested number of bytes and writing them out. This
1972 * is also where we jump to additional cabinets in the case of split
1973 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1975 static int fdi_decomp(const struct fdi_file
*fi
, int savemode
, fdi_decomp_state
*decomp_state
,
1976 char *pszCabPath
, PFNFDINOTIFY pfnfdin
, void *pvUser
)
1978 cab_ULONG bytes
= savemode
? fi
->length
: fi
->offset
- CAB(offset
);
1979 cab_UBYTE buf
[cfdata_SIZEOF
], *data
;
1980 cab_UWORD inlen
, len
, outlen
, cando
;
1983 fdi_decomp_state
*cab
= (savemode
&& CAB(decomp_cab
)) ? CAB(decomp_cab
) : decomp_state
;
1985 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi
, savemode
, bytes
);
1988 /* cando = the max number of bytes we can do */
1989 cando
= CAB(outlen
);
1990 if (cando
> bytes
) cando
= bytes
;
1993 if (cando
&& savemode
)
1994 CAB(fdi
)->write(CAB(filehf
), CAB(outpos
), cando
);
1996 CAB(outpos
) += cando
;
1997 CAB(outlen
) -= cando
;
1998 bytes
-= cando
; if (!bytes
) break;
2000 /* we only get here if we emptied the output buffer */
2002 /* read data header + data */
2004 while (outlen
== 0) {
2005 /* read the block header, skip the reserved part */
2006 if (CAB(fdi
)->read(cab
->cabhf
, buf
, cfdata_SIZEOF
) != cfdata_SIZEOF
)
2009 if (CAB(fdi
)->seek(cab
->cabhf
, cab
->mii
.block_resv
, SEEK_CUR
) == -1)
2012 /* we shouldn't get blocks over CAB_INPUTMAX in size */
2013 data
= CAB(inbuf
) + inlen
;
2014 len
= EndGetI16(buf
+cfdata_CompressedSize
);
2016 if (inlen
> CAB_INPUTMAX
) return DECR_INPUT
;
2017 if (CAB(fdi
)->read(cab
->cabhf
, data
, len
) != len
)
2020 /* clear two bytes after read-in data */
2021 data
[len
+1] = data
[len
+2] = 0;
2023 /* perform checksum test on the block (if one is stored) */
2024 cksum
= EndGetI32(buf
+cfdata_CheckSum
);
2025 if (cksum
&& cksum
!= checksum(buf
+4, 4, checksum(data
, len
, 0)))
2026 return DECR_CHECKSUM
; /* checksum is wrong */
2028 outlen
= EndGetI16(buf
+cfdata_UncompressedSize
);
2030 /* outlen=0 means this block was the last contiguous part
2031 of a split block, continued in the next cabinet */
2033 int pathlen
, filenamelen
;
2035 char fullpath
[MAX_PATH
], userpath
[256];
2036 FDINOTIFICATION fdin
;
2037 FDICABINETINFO fdici
;
2038 char emptystring
= '\0';
2040 int success
= FALSE
;
2041 struct fdi_folder
*fol
= NULL
, *linkfol
= NULL
;
2042 struct fdi_file
*file
= NULL
, *linkfile
= NULL
;
2046 /* set up the next decomp_state... */
2050 if (!cab
->mii
.hasnext
) return DECR_INPUT
;
2052 if (!((cab
->next
= CAB(fdi
)->alloc(sizeof(fdi_decomp_state
)))))
2053 return DECR_NOMEMORY
;
2055 ZeroMemory(cab
->next
, sizeof(fdi_decomp_state
));
2057 /* copy pszCabPath to userpath */
2058 ZeroMemory(userpath
, 256);
2059 pathlen
= pszCabPath
? strlen(pszCabPath
) : 0;
2061 if (pathlen
< 256) /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2062 strcpy(userpath
, pszCabPath
);
2065 /* initial fdintNEXT_CABINET notification */
2066 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2067 fdin
.psz1
= cab
->mii
.nextname
? cab
->mii
.nextname
: &emptystring
;
2068 fdin
.psz2
= cab
->mii
.nextinfo
? cab
->mii
.nextinfo
: &emptystring
;
2069 fdin
.psz3
= userpath
;
2070 fdin
.fdie
= FDIERROR_NONE
;
2073 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2077 pathlen
= strlen(userpath
);
2078 filenamelen
= cab
->mii
.nextname
? strlen(cab
->mii
.nextname
) : 0;
2080 /* slight overestimation here to save CPU cycles in the developer's brain */
2081 if ((pathlen
+ filenamelen
+ 3) > MAX_PATH
) {
2082 ERR("MAX_PATH exceeded.\n");
2083 return DECR_ILLEGALDATA
;
2086 /* paste the path and filename together */
2089 strcpy(fullpath
, userpath
);
2090 if (fullpath
[pathlen
- 1] != '\\')
2091 strcat(fullpath
, "\\");
2094 strcat(fullpath
, cab
->mii
.nextname
);
2096 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath
));
2098 /* try to get a handle to the cabfile */
2099 cabhf
= CAB(fdi
)->open(fullpath
, _O_RDONLY
|_O_BINARY
, _S_IREAD
| _S_IWRITE
);
2101 /* no file. allow the user to try again */
2102 fdin
.fdie
= FDIERROR_CABINET_NOT_FOUND
;
2103 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2108 ERR("PFDI_OPEN returned zero for %s.\n", fullpath
);
2109 fdin
.fdie
= FDIERROR_CABINET_NOT_FOUND
;
2110 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2114 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2115 if (!FDI_read_entries(CAB(fdi
), cabhf
, &fdici
, &(cab
->next
->mii
))) {
2116 WARN("FDIIsCabinet failed.\n");
2117 CAB(fdi
)->close(cabhf
);
2118 fdin
.fdie
= FDIERROR_NOT_A_CABINET
;
2119 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2123 if ((fdici
.setID
!= cab
->setID
) || (fdici
.iCabinet
!= (cab
->iCabinet
+ 1))) {
2124 WARN("Wrong Cabinet.\n");
2125 CAB(fdi
)->close(cabhf
);
2126 fdin
.fdie
= FDIERROR_WRONG_CABINET
;
2127 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2135 /* cabinet notification */
2136 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2137 fdin
.setID
= fdici
.setID
;
2138 fdin
.iCabinet
= fdici
.iCabinet
;
2140 fdin
.psz1
= (cab
->next
->mii
.nextname
) ? cab
->next
->mii
.nextname
: &emptystring
;
2141 fdin
.psz2
= (cab
->next
->mii
.nextinfo
) ? cab
->next
->mii
.nextinfo
: &emptystring
;
2142 fdin
.psz3
= pszCabPath
;
2144 if (((*pfnfdin
)(fdintCABINET_INFO
, &fdin
))) return DECR_USERABORT
;
2146 cab
->next
->setID
= fdici
.setID
;
2147 cab
->next
->iCabinet
= fdici
.iCabinet
;
2148 cab
->next
->fdi
= CAB(fdi
);
2149 cab
->next
->filehf
= CAB(filehf
);
2150 cab
->next
->cabhf
= cabhf
;
2151 cab
->next
->decompress
= CAB(decompress
); /* crude, but unused anyhow */
2153 cab
= cab
->next
; /* advance to the next cabinet */
2156 for (i
= 0; i
< fdici
.cFolders
; i
++) {
2157 if (CAB(fdi
)->read(cab
->cabhf
, buf2
, cffold_SIZEOF
) != cffold_SIZEOF
)
2160 if (cab
->mii
.folder_resv
> 0)
2161 CAB(fdi
)->seek(cab
->cabhf
, cab
->mii
.folder_resv
, SEEK_CUR
);
2163 fol
= CAB(fdi
)->alloc(sizeof(struct fdi_folder
));
2165 ERR("out of memory!\n");
2166 return DECR_NOMEMORY
;
2168 ZeroMemory(fol
, sizeof(struct fdi_folder
));
2169 if (!(cab
->firstfol
)) cab
->firstfol
= fol
;
2171 fol
->offset
= (cab_off_t
) EndGetI32(buf2
+cffold_DataOffset
);
2172 fol
->num_blocks
= EndGetI16(buf2
+cffold_NumBlocks
);
2173 fol
->comp_type
= EndGetI16(buf2
+cffold_CompType
);
2176 linkfol
->next
= fol
;
2181 for (i
= 0; i
< fdici
.cFiles
; i
++) {
2182 if (CAB(fdi
)->read(cab
->cabhf
, buf2
, cffile_SIZEOF
) != cffile_SIZEOF
)
2185 file
= CAB(fdi
)->alloc(sizeof(struct fdi_file
));
2187 ERR("out of memory!\n");
2188 return DECR_NOMEMORY
;
2190 ZeroMemory(file
, sizeof(struct fdi_file
));
2191 if (!(cab
->firstfile
)) cab
->firstfile
= file
;
2193 file
->length
= EndGetI32(buf2
+cffile_UncompressedSize
);
2194 file
->offset
= EndGetI32(buf2
+cffile_FolderOffset
);
2195 file
->index
= EndGetI16(buf2
+cffile_FolderIndex
);
2196 file
->time
= EndGetI16(buf2
+cffile_Time
);
2197 file
->date
= EndGetI16(buf2
+cffile_Date
);
2198 file
->attribs
= EndGetI16(buf2
+cffile_Attribs
);
2199 file
->filename
= FDI_read_string(CAB(fdi
), cab
->cabhf
, fdici
.cbCabinet
);
2201 if (!file
->filename
) return DECR_INPUT
;
2204 linkfile
->next
= file
;
2209 cab
= cab
->next
; /* advance to the next cabinet */
2211 /* iterate files -- if we encounter the continued file, process it --
2212 otherwise, jump to the label above and keep looking */
2214 for (file
= cab
->firstfile
; (file
); file
= file
->next
) {
2215 if ((file
->index
& cffileCONTINUED_FROM_PREV
) == cffileCONTINUED_FROM_PREV
) {
2216 /* check to ensure a real match */
2217 if (lstrcmpiA(fi
->filename
, file
->filename
) == 0) {
2219 if (CAB(fdi
)->seek(cab
->cabhf
, cab
->firstfol
->offset
, SEEK_SET
) == -1)
2225 if (!success
) goto tryanothercab
; /* FIXME: shouldn't this trigger
2226 "Wrong Cabinet" notification? */
2230 /* decompress block */
2231 if ((err
= CAB(decompress
)(inlen
, outlen
, decomp_state
)))
2233 CAB(outlen
) = outlen
;
2234 CAB(outpos
) = CAB(outbuf
);
2237 CAB(decomp_cab
) = cab
;
2241 static void free_decompression_temps(FDI_Int
*fdi
, const struct fdi_folder
*fol
,
2242 fdi_decomp_state
*decomp_state
)
2244 switch (fol
->comp_type
& cffoldCOMPTYPE_MASK
) {
2245 case cffoldCOMPTYPE_LZX
:
2247 fdi
->free(LZX(window
));
2251 case cffoldCOMPTYPE_QUANTUM
:
2253 fdi
->free(QTM(window
));
2260 static void free_decompression_mem(FDI_Int
*fdi
, fdi_decomp_state
*decomp_state
)
2262 struct fdi_folder
*fol
;
2263 while (decomp_state
) {
2264 fdi_decomp_state
*prev_fds
;
2266 fdi
->close(CAB(cabhf
));
2268 /* free the storage remembered by mii */
2269 if (CAB(mii
).nextname
) fdi
->free(CAB(mii
).nextname
);
2270 if (CAB(mii
).nextinfo
) fdi
->free(CAB(mii
).nextinfo
);
2271 if (CAB(mii
).prevname
) fdi
->free(CAB(mii
).prevname
);
2272 if (CAB(mii
).previnfo
) fdi
->free(CAB(mii
).previnfo
);
2274 while (CAB(firstfol
)) {
2275 fol
= CAB(firstfol
);
2276 CAB(firstfol
) = CAB(firstfol
)->next
;
2279 while (CAB(firstfile
)) {
2280 struct fdi_file
*file
= CAB(firstfile
);
2281 if (file
->filename
) fdi
->free(file
->filename
);
2282 CAB(firstfile
) = CAB(firstfile
)->next
;
2285 prev_fds
= decomp_state
;
2286 decomp_state
= CAB(next
);
2287 fdi
->free(prev_fds
);
2291 /***********************************************************************
2292 * FDICopy (CABINET.22)
2294 * Iterates through the files in the Cabinet file indicated by name and
2295 * file-location. May chain forward to additional cabinets (typically
2296 * only one) if files which begin in this Cabinet are continued in another
2297 * cabinet. For each file which is partially contained in this cabinet,
2298 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2299 * notification to the pfnfdin callback. For each file which begins in
2300 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2301 * callback, and the file is optionally decompressed and saved to disk.
2302 * Notification is not provided for files which are not at least partially
2303 * contained in the specified cabinet file.
2305 * See below for a thorough explanation of the various notification
2309 * hfdi [I] An HFDI from FDICreate
2310 * pszCabinet [I] C-style string containing the filename of the cabinet
2311 * pszCabPath [I] C-style string containing the file path of the cabinet
2312 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2313 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2314 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2316 * pvUser [I] arbitrary void * value which is passed to callbacks.
2319 * TRUE if successful.
2320 * FALSE if unsuccessful (error information is provided in the ERF structure
2321 * associated with the provided decompression handle by FDICreate).
2325 * Two pointers to callback functions are provided as parameters to FDICopy:
2326 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2327 * types are as follows:
2329 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2330 * PFDINOTIFICATION pfdin );
2332 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2334 * You can create functions of this type using the FNFDINOTIFY() and
2335 * FNFDIDECRYPT() macros, respectively. For example:
2337 * FNFDINOTIFY(mycallback) {
2338 * / * use variables fdint and pfdin to process notification * /
2341 * The second callback, which could be used for decrypting encrypted data,
2342 * is not used at all.
2344 * Each notification informs the user of some event which has occurred during
2345 * decompression of the cabinet file; each notification is also an opportunity
2346 * for the callee to abort decompression. The information provided to the
2347 * callback and the meaning of the callback's return value vary drastically
2348 * across the various types of notification. The type of notification is the
2349 * fdint parameter; all other information is provided to the callback in
2350 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2351 * pfdin. The only part of that structure which is assigned for every callback
2352 * is the pv element, which contains the arbitrary value which was passed to
2353 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2354 * is highly dependent on fdint).
2356 * If you encounter unknown notifications, you should return zero if you want
2357 * decompression to continue (or -1 to abort). All strings used in the
2358 * callbacks are regular C-style strings. Detailed descriptions of each
2359 * notification type follow:
2361 * fdintCABINET_INFO:
2363 * This is the first notification provided after calling FDICopy, and provides
2364 * the user with various information about the cabinet. Note that this is
2365 * called for each cabinet FDICopy opens, not just the first one. In the
2366 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2367 * next cabinet file in the set after the one just loaded (if any), psz2
2368 * contains a pointer to the name or "info" of the next disk, psz3
2369 * contains a pointer to the file-path of the current cabinet, setID
2370 * contains an arbitrary constant associated with this set of cabinet files,
2371 * and iCabinet contains the numerical index of the current cabinet within
2372 * that set. Return zero, or -1 to abort.
2374 * fdintPARTIAL_FILE:
2376 * This notification is provided when FDICopy encounters a part of a file
2377 * contained in this cabinet which is missing its beginning. Files can be
2378 * split across cabinets, so this is not necessarily an abnormality; it just
2379 * means that the file in question begins in another cabinet. No file
2380 * corresponding to this notification is extracted from the cabinet. In the
2381 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2382 * partial file, psz2 contains a pointer to the file name of the cabinet in
2383 * which this file begins, and psz3 contains a pointer to the disk name or
2384 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2388 * This notification is provided when FDICopy encounters a file which starts
2389 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2390 * look for files in cabinets after the first one). One notification will be
2391 * sent for each such file, before the file is decompressed. By returning
2392 * zero, the callback can instruct FDICopy to skip the file. In the structure
2393 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2394 * the size of the file (uncompressed), attribs contains the file attributes,
2395 * and date and time contain the date and time of the file. attributes, date,
2396 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2397 * for the entire cabinet, 0 to skip just this file but continue scanning the
2398 * cabinet for more files, or an FDIClose()-compatible file-handle.
2400 * fdintCLOSE_FILE_INFO:
2402 * This notification is important, don't forget to implement it. This
2403 * notification indicates that a file has been successfully uncompressed and
2404 * written to disk. Upon receipt of this notification, the callee is expected
2405 * to close the file handle, to set the attributes and date/time of the
2406 * closed file, and possibly to execute the file. In the structure pointed to
2407 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2408 * open file handle (close it), cb contains 1 or zero, indicating respectively
2409 * that the callee should or should not execute the file, and date, time
2410 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2411 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2412 * do so. Return TRUE, or FALSE to abort decompression.
2414 * fdintNEXT_CABINET:
2416 * This notification is called when FDICopy must load in another cabinet. This
2417 * can occur when a file's data is "split" across multiple cabinets. The
2418 * callee has the opportunity to request that FDICopy look in a different file
2419 * path for the specified cabinet file, by writing that data into a provided
2420 * buffer (see below for more information). This notification will be received
2421 * more than once per-cabinet in the instance that FDICopy failed to find a
2422 * valid cabinet at the location specified by the first per-cabinet
2423 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2424 * structure pointed to by pfdin indicates the error which prevented FDICopy
2425 * from proceeding successfully. Return zero to indicate success, or -1 to
2426 * indicate failure and abort FDICopy.
2428 * Upon receipt of this notification, the structure pointed to by pfdin will
2429 * contain the following values: psz1 pointing to the name of the cabinet
2430 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2431 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2432 * and fdie containing either FDIERROR_NONE, or one of the following:
2434 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2435 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2436 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2437 * FDIERROR_WRONG_CABINET.
2439 * The callee may choose to change the path where FDICopy will look for the
2440 * cabinet after this notification. To do so, the caller may write the new
2441 * pathname to the buffer pointed to by psz3, which is 256 characters in
2442 * length, including the terminating null character, before returning zero.
2446 * Undocumented and unimplemented in wine, this seems to be sent each time
2447 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2448 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2449 * provides information about the current cabinet instead of the next one....
2450 * this is just a guess, it has not been looked at closely.
2455 BOOL __cdecl
FDICopy(
2460 PFNFDINOTIFY pfnfdin
,
2461 PFNFDIDECRYPT pfnfdid
,
2464 FDICABINETINFO fdici
;
2465 FDINOTIFICATION fdin
;
2466 INT_PTR cabhf
, filehf
= 0;
2468 char fullpath
[MAX_PATH
];
2469 size_t pathlen
, filenamelen
;
2470 char emptystring
= '\0';
2472 struct fdi_folder
*fol
= NULL
, *linkfol
= NULL
;
2473 struct fdi_file
*file
= NULL
, *linkfile
= NULL
;
2474 fdi_decomp_state
*decomp_state
;
2475 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
2477 TRACE("(hfdi == ^%p, pszCabinet == %s, pszCabPath == %s, flags == %x, "
2478 "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2479 hfdi
, debugstr_a(pszCabinet
), debugstr_a(pszCabPath
), flags
, pfnfdin
, pfnfdid
, pvUser
);
2481 if (!fdi
) return FALSE
;
2483 if (!(decomp_state
= fdi
->alloc(sizeof(fdi_decomp_state
))))
2485 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2488 ZeroMemory(decomp_state
, sizeof(fdi_decomp_state
));
2490 pathlen
= pszCabPath
? strlen(pszCabPath
) : 0;
2491 filenamelen
= pszCabinet
? strlen(pszCabinet
) : 0;
2493 /* slight overestimation here to save CPU cycles in the developer's brain */
2494 if ((pathlen
+ filenamelen
+ 3) > MAX_PATH
) {
2495 ERR("MAX_PATH exceeded.\n");
2496 fdi
->free(decomp_state
);
2497 set_error( fdi
, FDIERROR_CABINET_NOT_FOUND
, ERROR_FILE_NOT_FOUND
);
2501 /* paste the path and filename together */
2504 strcpy(fullpath
, pszCabPath
);
2506 strcat(fullpath
, pszCabinet
);
2508 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath
));
2510 /* get a handle to the cabfile */
2511 cabhf
= fdi
->open(fullpath
, _O_RDONLY
|_O_BINARY
, _S_IREAD
| _S_IWRITE
);
2513 fdi
->free(decomp_state
);
2514 set_error( fdi
, FDIERROR_CABINET_NOT_FOUND
, 0 );
2515 SetLastError(ERROR_FILE_NOT_FOUND
);
2519 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2520 if (!FDI_read_entries(fdi
, cabhf
, &fdici
, &(CAB(mii
)))) {
2521 WARN("FDI_read_entries failed: %u\n", fdi
->perf
->erfOper
);
2522 fdi
->free(decomp_state
);
2527 /* cabinet notification */
2528 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2529 fdin
.setID
= fdici
.setID
;
2530 fdin
.iCabinet
= fdici
.iCabinet
;
2532 fdin
.psz1
= (CAB(mii
).nextname
) ? CAB(mii
).nextname
: &emptystring
;
2533 fdin
.psz2
= (CAB(mii
).nextinfo
) ? CAB(mii
).nextinfo
: &emptystring
;
2534 fdin
.psz3
= pszCabPath
;
2536 if (((*pfnfdin
)(fdintCABINET_INFO
, &fdin
))) {
2537 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2541 CAB(setID
) = fdici
.setID
;
2542 CAB(iCabinet
) = fdici
.iCabinet
;
2546 for (i
= 0; i
< fdici
.cFolders
; i
++) {
2547 if (fdi
->read(cabhf
, buf
, cffold_SIZEOF
) != cffold_SIZEOF
) {
2548 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2552 if (CAB(mii
).folder_resv
> 0)
2553 fdi
->seek(cabhf
, CAB(mii
).folder_resv
, SEEK_CUR
);
2555 fol
= fdi
->alloc(sizeof(struct fdi_folder
));
2557 ERR("out of memory!\n");
2558 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2561 ZeroMemory(fol
, sizeof(struct fdi_folder
));
2562 if (!CAB(firstfol
)) CAB(firstfol
) = fol
;
2564 fol
->offset
= (cab_off_t
) EndGetI32(buf
+cffold_DataOffset
);
2565 fol
->num_blocks
= EndGetI16(buf
+cffold_NumBlocks
);
2566 fol
->comp_type
= EndGetI16(buf
+cffold_CompType
);
2569 linkfol
->next
= fol
;
2574 for (i
= 0; i
< fdici
.cFiles
; i
++) {
2575 if (fdi
->read(cabhf
, buf
, cffile_SIZEOF
) != cffile_SIZEOF
) {
2576 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2580 file
= fdi
->alloc(sizeof(struct fdi_file
));
2582 ERR("out of memory!\n");
2583 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2586 ZeroMemory(file
, sizeof(struct fdi_file
));
2587 if (!CAB(firstfile
)) CAB(firstfile
) = file
;
2589 file
->length
= EndGetI32(buf
+cffile_UncompressedSize
);
2590 file
->offset
= EndGetI32(buf
+cffile_FolderOffset
);
2591 file
->index
= EndGetI16(buf
+cffile_FolderIndex
);
2592 file
->time
= EndGetI16(buf
+cffile_Time
);
2593 file
->date
= EndGetI16(buf
+cffile_Date
);
2594 file
->attribs
= EndGetI16(buf
+cffile_Attribs
);
2595 file
->filename
= FDI_read_string(fdi
, cabhf
, fdici
.cbCabinet
);
2597 if (!file
->filename
) {
2598 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2603 linkfile
->next
= file
;
2607 for (file
= CAB(firstfile
); (file
); file
= file
->next
) {
2610 * FIXME: This implementation keeps multiple cabinet files open at once
2611 * when encountering a split cabinet. It is a quirk of this implementation
2612 * that sometimes we decrypt the same block of data more than once, to find
2613 * the right starting point for a file, moving the file-pointer backwards.
2614 * If we kept a cache of certain file-pointer information, we could eliminate
2615 * that behavior... in fact I am not sure that the caching we already have
2616 * is not sufficient.
2618 * The current implementation seems to work fine in straightforward situations
2619 * where all the cabinet files needed for decryption are simultaneously
2620 * available. But presumably, the API is supposed to support cabinets which
2621 * are split across multiple CDROMS; we may need to change our implementation
2622 * to strictly serialize it's file usage so that it opens only one cabinet
2623 * at a time. Some experimentation with Windows is needed to figure out the
2624 * precise semantics required. The relevant code is here and in fdi_decomp().
2627 /* partial-file notification */
2628 if ((file
->index
& cffileCONTINUED_FROM_PREV
) == cffileCONTINUED_FROM_PREV
) {
2630 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2631 * and perform some tests to figure out the right behavior. The SDK says
2632 * FDICopy will notify the user of the filename and "disk name" (info) of
2633 * the cabinet where the spanning file /started/.
2635 * That would certainly be convenient for the API-user, who could abort,
2636 * everything (or parallelize, if that's allowed (it is in wine)), and call
2637 * FDICopy again with the provided filename, so as to avoid partial file
2638 * notification and successfully unpack. This task could be quite unpleasant
2639 * from wine's perspective: the information specifying the "start cabinet" for
2640 * a file is associated nowhere with the file header and is not to be found in
2641 * the cabinet header. We have only the index of the cabinet wherein the folder
2642 * begins, which contains the file. To find that cabinet, we must consider the
2643 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2644 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2647 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2648 * cabinet other than the active one might be at another filepath than the
2649 * current one, or on another CDROM. This could get rather dicey, especially
2650 * if we imagine parallelized access to the FDICopy API.
2652 * The current implementation punts -- it just returns the previous cabinet and
2653 * it's info from the header of this cabinet. This provides the right answer in
2654 * 95% of the cases; its worth checking if Microsoft cuts the same corner before
2657 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2659 fdin
.psz1
= (char *)file
->filename
;
2660 fdin
.psz2
= (CAB(mii
).prevname
) ? CAB(mii
).prevname
: &emptystring
;
2661 fdin
.psz3
= (CAB(mii
).previnfo
) ? CAB(mii
).previnfo
: &emptystring
;
2663 if (((*pfnfdin
)(fdintPARTIAL_FILE
, &fdin
))) {
2664 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2667 /* I don't think we are supposed to decompress partial files. This prevents it. */
2668 file
->oppressed
= TRUE
;
2670 if (file
->oppressed
) {
2673 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2675 fdin
.psz1
= (char *)file
->filename
;
2676 fdin
.cb
= file
->length
;
2677 fdin
.date
= file
->date
;
2678 fdin
.time
= file
->time
;
2679 fdin
.attribs
= file
->attribs
;
2680 if ((filehf
= ((*pfnfdin
)(fdintCOPY_FILE
, &fdin
))) == -1) {
2681 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2687 /* find the folder for this file if necc. */
2689 fol
= CAB(firstfol
);
2690 if ((file
->index
& cffileCONTINUED_TO_NEXT
) == cffileCONTINUED_TO_NEXT
) {
2691 /* pick the last folder */
2692 while (fol
->next
) fol
= fol
->next
;
2696 for (i2
= 0; (i2
< file
->index
); i2
++)
2697 if (fol
->next
) /* bug resistance, should always be true */
2703 cab_UWORD comptype
= fol
->comp_type
;
2704 int ct1
= comptype
& cffoldCOMPTYPE_MASK
;
2705 int ct2
= CAB(current
) ? (CAB(current
)->comp_type
& cffoldCOMPTYPE_MASK
) : 0;
2708 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file
->filename
));
2710 /* set up decomp_state */
2712 CAB(filehf
) = filehf
;
2714 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2715 if ((ct1
!= ct2
) || (CAB(current
) != fol
) || (file
->offset
< CAB(offset
))) {
2717 TRACE("Resetting folder for file %s.\n", debugstr_a(file
->filename
));
2719 /* free stuff for the old decompressor */
2721 case cffoldCOMPTYPE_LZX
:
2723 fdi
->free(LZX(window
));
2727 case cffoldCOMPTYPE_QUANTUM
:
2729 fdi
->free(QTM(window
));
2735 CAB(decomp_cab
) = NULL
;
2736 CAB(fdi
)->seek(CAB(cabhf
), fol
->offset
, SEEK_SET
);
2740 /* initialize the new decompressor */
2742 case cffoldCOMPTYPE_NONE
:
2743 CAB(decompress
) = NONEfdi_decomp
;
2745 case cffoldCOMPTYPE_MSZIP
:
2746 CAB(decompress
) = ZIPfdi_decomp
;
2748 case cffoldCOMPTYPE_QUANTUM
:
2749 CAB(decompress
) = QTMfdi_decomp
;
2750 err
= QTMfdi_init((comptype
>> 8) & 0x1f, (comptype
>> 4) & 0xF, decomp_state
);
2752 case cffoldCOMPTYPE_LZX
:
2753 CAB(decompress
) = LZXfdi_decomp
;
2754 err
= LZXfdi_init((comptype
>> 8) & 0x1f, decomp_state
);
2757 err
= DECR_DATAFORMAT
;
2767 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2770 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2774 if (file
->offset
> CAB(offset
)) {
2775 /* decode bytes and send them to /dev/null */
2776 switch (fdi_decomp(file
, 0, decomp_state
, pszCabPath
, pfnfdin
, pvUser
)) {
2779 case DECR_USERABORT
:
2780 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2783 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2786 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2789 CAB(offset
) = file
->offset
;
2792 /* now do the actual decompression */
2793 err
= fdi_decomp(file
, 1, decomp_state
, pszCabPath
, pfnfdin
, pvUser
);
2794 if (err
) CAB(current
) = NULL
; else CAB(offset
) += file
->length
;
2796 /* fdintCLOSE_FILE_INFO notification */
2797 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2799 fdin
.psz1
= (char *)file
->filename
;
2801 fdin
.cb
= (file
->attribs
& cffile_A_EXEC
) != 0; /* FIXME: is that right? */
2802 fdin
.date
= file
->date
;
2803 fdin
.time
= file
->time
;
2804 fdin
.attribs
= file
->attribs
; /* FIXME: filter _A_EXEC? */
2805 ((*pfnfdin
)(fdintCLOSE_FILE_INFO
, &fdin
));
2811 case DECR_USERABORT
:
2812 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2815 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2818 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2824 if (fol
) free_decompression_temps(fdi
, fol
, decomp_state
);
2825 free_decompression_mem(fdi
, decomp_state
);
2829 bail_and_fail
: /* here we free ram before error returns */
2831 if (fol
) free_decompression_temps(fdi
, fol
, decomp_state
);
2833 if (filehf
) fdi
->close(filehf
);
2835 free_decompression_mem(fdi
, decomp_state
);
2840 /***********************************************************************
2841 * FDIDestroy (CABINET.23)
2843 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2844 * of FDICopy. Only reason for failure would be an invalid handle.
2847 * hfdi [I] The HFDI to free
2853 BOOL __cdecl
FDIDestroy(HFDI hfdi
)
2855 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
2857 TRACE("(hfdi == ^%p)\n", hfdi
);
2858 if (!fdi
) return FALSE
;
2859 fdi
->magic
= 0; /* paranoia */
2864 /***********************************************************************
2865 * FDITruncateCabinet (CABINET.24)
2867 * Removes all folders of a cabinet file after and including the
2868 * specified folder number.
2871 * hfdi [I] Handle to the FDI context.
2872 * pszCabinetName [I] Filename of the cabinet.
2873 * iFolderToDelete [I] Index of the first folder to delete.
2880 * The PFNWRITE function supplied to FDICreate must truncate the
2881 * file at the current position if the number of bytes to write is 0.
2883 BOOL __cdecl
FDITruncateCabinet(
2885 char *pszCabinetName
,
2886 USHORT iFolderToDelete
)
2888 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
2890 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2891 hfdi
, debugstr_a(pszCabinetName
), iFolderToDelete
);
2893 if (!fdi
) return FALSE
;
2895 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);