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 * where 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_BAD_ARGUMENTS
);
698 rv
= FDI_read_entries(fdi
, hf
, pfdici
, NULL
);
701 pfdici
->hasnext
= FALSE
; /* yuck. duplicate apparent cabinet.dll bug */
706 /******************************************************************
707 * QTMfdi_initmodel (internal)
709 * Initialize a model which decodes symbols from [s] to [s]+[n]-1
711 static void QTMfdi_initmodel(struct QTMmodel
*m
, struct QTMmodelsym
*sym
, int n
, int s
) {
716 memset(m
->tabloc
, 0xFF, sizeof(m
->tabloc
)); /* clear out look-up table */
717 for (i
= 0; i
< n
; i
++) {
718 m
->tabloc
[i
+s
] = i
; /* set up a look-up entry for symbol */
719 m
->syms
[i
].sym
= i
+s
; /* actual symbol */
720 m
->syms
[i
].cumfreq
= n
-i
; /* current frequency of that symbol */
722 m
->syms
[n
].cumfreq
= 0;
725 /******************************************************************
726 * QTMfdi_init (internal)
728 static int QTMfdi_init(int window
, int level
, fdi_decomp_state
*decomp_state
) {
729 unsigned int wndsize
= 1 << window
;
730 int msz
= window
* 2, i
;
733 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
734 /* if a previously allocated window is big enough, keep it */
735 if (window
< 10 || window
> 21) return DECR_DATAFORMAT
;
736 if (QTM(actual_size
) < wndsize
) {
737 if (QTM(window
)) CAB(fdi
)->free(QTM(window
));
741 if (!(QTM(window
) = CAB(fdi
)->alloc(wndsize
))) return DECR_NOMEMORY
;
742 QTM(actual_size
) = wndsize
;
744 QTM(window_size
) = wndsize
;
745 QTM(window_posn
) = 0;
747 /* initialize static slot/extrabits tables */
748 for (i
= 0, j
= 0; i
< 27; i
++) {
749 CAB(q_length_extra
)[i
] = (i
== 26) ? 0 : (i
< 2 ? 0 : i
- 2) >> 2;
750 CAB(q_length_base
)[i
] = j
; j
+= 1 << ((i
== 26) ? 5 : CAB(q_length_extra
)[i
]);
752 for (i
= 0, j
= 0; i
< 42; i
++) {
753 CAB(q_extra_bits
)[i
] = (i
< 2 ? 0 : i
-2) >> 1;
754 CAB(q_position_base
)[i
] = j
; j
+= 1 << CAB(q_extra_bits
)[i
];
757 /* initialize arithmetic coding models */
759 QTMfdi_initmodel(&QTM(model7
), QTM(m7sym
), 7, 0);
761 QTMfdi_initmodel(&QTM(model00
), QTM(m00sym
), 0x40, 0x00);
762 QTMfdi_initmodel(&QTM(model40
), QTM(m40sym
), 0x40, 0x40);
763 QTMfdi_initmodel(&QTM(model80
), QTM(m80sym
), 0x40, 0x80);
764 QTMfdi_initmodel(&QTM(modelC0
), QTM(mC0sym
), 0x40, 0xC0);
766 /* model 4 depends on table size, ranges from 20 to 24 */
767 QTMfdi_initmodel(&QTM(model4
), QTM(m4sym
), (msz
< 24) ? msz
: 24, 0);
768 /* model 5 depends on table size, ranges from 20 to 36 */
769 QTMfdi_initmodel(&QTM(model5
), QTM(m5sym
), (msz
< 36) ? msz
: 36, 0);
770 /* model 6pos depends on table size, ranges from 20 to 42 */
771 QTMfdi_initmodel(&QTM(model6pos
), QTM(m6psym
), msz
, 0);
772 QTMfdi_initmodel(&QTM(model6len
), QTM(m6lsym
), 27, 0);
777 /************************************************************
778 * LZXfdi_init (internal)
780 static int LZXfdi_init(int window
, fdi_decomp_state
*decomp_state
) {
781 static const cab_UBYTE bits
[] =
782 { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
783 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14,
784 15, 15, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
786 static const cab_ULONG base
[] =
787 { 0, 1, 2, 3, 4, 6, 8, 12,
788 16, 24, 32, 48, 64, 96, 128, 192,
789 256, 384, 512, 768, 1024, 1536, 2048, 3072,
790 4096, 6144, 8192, 12288, 16384, 24576, 32768, 49152,
791 65536, 98304, 131072, 196608, 262144, 393216, 524288, 655360,
792 786432, 917504, 1048576, 1179648, 1310720, 1441792, 1572864, 1703936,
793 1835008, 1966080, 2097152};
794 cab_ULONG wndsize
= 1 << window
;
797 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
798 /* if a previously allocated window is big enough, keep it */
799 if (window
< 15 || window
> 21) return DECR_DATAFORMAT
;
800 if (LZX(actual_size
) < wndsize
) {
801 if (LZX(window
)) CAB(fdi
)->free(LZX(window
));
805 if (!(LZX(window
) = CAB(fdi
)->alloc(wndsize
))) return DECR_NOMEMORY
;
806 LZX(actual_size
) = wndsize
;
808 LZX(window_size
) = wndsize
;
810 /* initialize static tables */
811 memcpy(CAB(extra_bits
), bits
, sizeof(bits
));
812 memcpy(CAB(lzx_position_base
), base
, sizeof(base
));
814 /* calculate required position slots */
815 if (window
== 20) posn_slots
= 42;
816 else if (window
== 21) posn_slots
= 50;
817 else posn_slots
= window
<< 1;
819 /*posn_slots=i=0; while (i < wndsize) i += 1 << CAB(extra_bits)[posn_slots++]; */
821 LZX(R0
) = LZX(R1
) = LZX(R2
) = 1;
822 LZX(main_elements
) = LZX_NUM_CHARS
+ (posn_slots
<< 3);
823 LZX(header_read
) = 0;
824 LZX(frames_read
) = 0;
825 LZX(block_remaining
) = 0;
826 LZX(block_type
) = LZX_BLOCKTYPE_INVALID
;
827 LZX(intel_curpos
) = 0;
828 LZX(intel_started
) = 0;
829 LZX(window_posn
) = 0;
831 /* initialize tables to 0 (because deltas will be applied to them) */
832 memset(LZX(MAINTREE_len
), 0, sizeof(LZX(MAINTREE_len
)));
833 memset(LZX(LENGTH_len
), 0, sizeof(LZX(LENGTH_len
)));
838 /****************************************************
839 * NONEfdi_decomp(internal)
841 static int NONEfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
843 if (inlen
!= outlen
) return DECR_ILLEGALDATA
;
844 if (outlen
> CAB_BLOCKMAX
) return DECR_DATAFORMAT
;
845 memcpy(CAB(outbuf
), CAB(inbuf
), (size_t) inlen
);
849 /********************************************************
850 * Ziphuft_free (internal)
852 static void fdi_Ziphuft_free(FDI_Int
*fdi
, struct Ziphuft
*t
)
854 register struct Ziphuft
*p
, *q
;
856 /* Go through linked list, freeing from the allocated (t[-1]) address. */
866 /*********************************************************
867 * fdi_Ziphuft_build (internal)
869 static cab_LONG
fdi_Ziphuft_build(cab_ULONG
*b
, cab_ULONG n
, cab_ULONG s
, const cab_UWORD
*d
, const cab_UWORD
*e
,
870 struct Ziphuft
**t
, cab_LONG
*m
, fdi_decomp_state
*decomp_state
)
872 cab_ULONG a
; /* counter for codes of length k */
873 cab_ULONG el
; /* length of EOB code (value 256) */
874 cab_ULONG f
; /* i repeats in table every f entries */
875 cab_LONG g
; /* maximum code length */
876 cab_LONG h
; /* table level */
877 register cab_ULONG i
; /* counter, current code */
878 register cab_ULONG j
; /* counter */
879 register cab_LONG k
; /* number of bits in current code */
880 cab_LONG
*l
; /* stack of bits per table */
881 register cab_ULONG
*p
; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
882 register struct Ziphuft
*q
; /* points to current table */
883 struct Ziphuft r
; /* table entry for structure assignment */
884 register cab_LONG w
; /* bits before this table == (l * h) */
885 cab_ULONG
*xp
; /* pointer into x */
886 cab_LONG y
; /* number of dummy codes added */
887 cab_ULONG z
; /* number of entries in current table */
891 /* Generate counts for each bit length */
892 el
= n
> 256 ? b
[256] : ZIPBMAX
; /* set length of EOB code, if any */
894 for(i
= 0; i
< ZIPBMAX
+1; ++i
)
899 ZIP(c
)[*p
]++; p
++; /* assume all entries <= ZIPBMAX */
901 if (ZIP(c
)[0] == n
) /* null input--all zero length codes */
908 /* Find minimum and maximum length, bound *m by those */
909 for (j
= 1; j
<= ZIPBMAX
; j
++)
912 k
= j
; /* minimum code length */
913 if ((cab_ULONG
)*m
< j
)
915 for (i
= ZIPBMAX
; i
; i
--)
918 g
= i
; /* maximum code length */
919 if ((cab_ULONG
)*m
> i
)
922 /* Adjust last length count to fill out codes, if needed */
923 for (y
= 1 << j
; j
< i
; j
++, y
<<= 1)
924 if ((y
-= ZIP(c
)[j
]) < 0)
925 return 2; /* bad input: more codes than bits */
926 if ((y
-= ZIP(c
)[i
]) < 0)
930 /* Generate starting offsets LONGo the value table for each length */
932 p
= ZIP(c
) + 1; xp
= ZIP(x
) + 2;
934 { /* note that i == g from above */
938 /* Make a table of values in order of bit lengths */
942 ZIP(v
)[ZIP(x
)[j
]++] = i
;
946 /* Generate the Huffman codes and for each, make the table entries */
947 ZIP(x
)[0] = i
= 0; /* first Huffman code is zero */
948 p
= ZIP(v
); /* grab values in bit order */
949 h
= -1; /* no tables yet--level -1 */
950 w
= l
[-1] = 0; /* no bits decoded yet */
951 ZIP(u
)[0] = NULL
; /* just to keep compilers happy */
952 q
= NULL
; /* ditto */
955 /* go through the bit lengths (k already is bits in shortest code) */
961 /* here i is the Huffman code of length k bits for value *p */
962 /* make tables up to required level */
965 w
+= l
[h
++]; /* add bits already decoded */
967 /* compute minimum size table less than or equal to *m bits */
968 if ((z
= g
- w
) > (cab_ULONG
)*m
) /* upper limit */
970 if ((f
= 1 << (j
= k
- w
)) > a
+ 1) /* try a k-w bit table */
971 { /* too few codes for k-w bit table */
972 f
-= a
+ 1; /* deduct codes from patterns left */
974 while (++j
< z
) /* try smaller tables up to z bits */
976 if ((f
<<= 1) <= *++xp
)
977 break; /* enough codes to use up j bits */
978 f
-= *xp
; /* else deduct codes from patterns */
981 if ((cab_ULONG
)w
+ j
> el
&& (cab_ULONG
)w
< el
)
982 j
= el
- w
; /* make EOB code end at table */
983 z
= 1 << j
; /* table entries for j-bit table */
984 l
[h
] = j
; /* set table size in stack */
986 /* allocate and link in new table */
987 if (!(q
= CAB(fdi
)->alloc((z
+ 1)*sizeof(struct Ziphuft
))))
990 fdi_Ziphuft_free(CAB(fdi
), ZIP(u
)[0]);
991 return 3; /* not enough memory */
993 *t
= q
+ 1; /* link to list for Ziphuft_free() */
994 *(t
= &(q
->v
.t
)) = NULL
;
995 ZIP(u
)[h
] = ++q
; /* table starts after link */
997 /* connect to last table, if there is one */
1000 ZIP(x
)[h
] = i
; /* save pattern for backing up */
1001 r
.b
= (cab_UBYTE
)l
[h
-1]; /* bits to dump before this table */
1002 r
.e
= (cab_UBYTE
)(16 + j
); /* bits in this table */
1003 r
.v
.t
= q
; /* pointer to this table */
1004 j
= (i
& ((1 << w
) - 1)) >> (w
- l
[h
-1]);
1005 ZIP(u
)[h
-1][j
] = r
; /* connect to last table */
1009 /* set up table entry in r */
1010 r
.b
= (cab_UBYTE
)(k
- w
);
1011 if (p
>= ZIP(v
) + n
)
1012 r
.e
= 99; /* out of values--invalid code */
1015 r
.e
= (cab_UBYTE
)(*p
< 256 ? 16 : 15); /* 256 is end-of-block code */
1016 r
.v
.n
= *p
++; /* simple code is just the value */
1020 r
.e
= (cab_UBYTE
)e
[*p
- s
]; /* non-simple--look up in lists */
1021 r
.v
.n
= d
[*p
++ - s
];
1024 /* fill code-like entries with r */
1026 for (j
= i
>> w
; j
< z
; j
+= f
)
1029 /* backwards increment the k-bit code i */
1030 for (j
= 1 << (k
- 1); i
& j
; j
>>= 1)
1034 /* backup over finished tables */
1035 while ((i
& ((1 << w
) - 1)) != ZIP(x
)[h
])
1036 w
-= l
[--h
]; /* don't need to update q */
1040 /* return actual size of base table */
1043 /* Return true (1) if we were given an incomplete table */
1044 return y
!= 0 && g
!= 1;
1047 /*********************************************************
1048 * fdi_Zipinflate_codes (internal)
1050 static cab_LONG
fdi_Zipinflate_codes(const struct Ziphuft
*tl
, const struct Ziphuft
*td
,
1051 cab_LONG bl
, cab_LONG bd
, fdi_decomp_state
*decomp_state
)
1053 register cab_ULONG e
; /* table entry flag/number of extra bits */
1054 cab_ULONG n
, d
; /* length and index for copy */
1055 cab_ULONG w
; /* current window position */
1056 const struct Ziphuft
*t
; /* pointer to table entry */
1057 cab_ULONG ml
, md
; /* masks for bl and bd bits */
1058 register cab_ULONG b
; /* bit buffer */
1059 register cab_ULONG k
; /* number of bits in bit buffer */
1061 /* make local copies of globals */
1062 b
= ZIP(bb
); /* initialize bit buffer */
1064 w
= ZIP(window_posn
); /* initialize window position */
1066 /* inflate the coded data */
1067 ml
= Zipmask
[bl
]; /* precompute masks for speed */
1072 ZIPNEEDBITS((cab_ULONG
)bl
)
1073 if((e
= (t
= tl
+ (b
& ml
))->e
) > 16)
1081 } while ((e
= (t
= t
->v
.t
+ (b
& Zipmask
[e
]))->e
) > 16);
1083 if (e
== 16) /* then it's a literal */
1084 CAB(outbuf
)[w
++] = (cab_UBYTE
)t
->v
.n
;
1085 else /* it's an EOB or a length */
1087 /* exit if end of block */
1091 /* get length of block to copy */
1093 n
= t
->v
.n
+ (b
& Zipmask
[e
]);
1096 /* decode distance of block to copy */
1097 ZIPNEEDBITS((cab_ULONG
)bd
)
1098 if ((e
= (t
= td
+ (b
& md
))->e
) > 16)
1105 } while ((e
= (t
= t
->v
.t
+ (b
& Zipmask
[e
]))->e
) > 16);
1108 d
= w
- t
->v
.n
- (b
& Zipmask
[e
]);
1113 e
= ZIPWSIZE
- max(d
, w
);
1118 CAB(outbuf
)[w
++] = CAB(outbuf
)[d
++];
1124 /* restore the globals from the locals */
1125 ZIP(window_posn
) = w
; /* restore global window pointer */
1126 ZIP(bb
) = b
; /* restore global bit buffer */
1133 /***********************************************************
1134 * Zipinflate_stored (internal)
1136 static cab_LONG
fdi_Zipinflate_stored(fdi_decomp_state
*decomp_state
)
1137 /* "decompress" an inflated type 0 (stored) block. */
1139 cab_ULONG n
; /* number of bytes in block */
1140 cab_ULONG w
; /* current window position */
1141 register cab_ULONG b
; /* bit buffer */
1142 register cab_ULONG k
; /* number of bits in bit buffer */
1144 /* make local copies of globals */
1145 b
= ZIP(bb
); /* initialize bit buffer */
1147 w
= ZIP(window_posn
); /* initialize window position */
1149 /* go to byte boundary */
1153 /* get the length and its complement */
1158 if (n
!= ((~b
) & 0xffff))
1159 return 1; /* error in compressed data */
1162 /* read and output the compressed data */
1166 CAB(outbuf
)[w
++] = (cab_UBYTE
)b
;
1170 /* restore the globals from the locals */
1171 ZIP(window_posn
) = w
; /* restore global window pointer */
1172 ZIP(bb
) = b
; /* restore global bit buffer */
1177 /******************************************************
1178 * fdi_Zipinflate_fixed (internal)
1180 static cab_LONG
fdi_Zipinflate_fixed(fdi_decomp_state
*decomp_state
)
1182 struct Ziphuft
*fixed_tl
;
1183 struct Ziphuft
*fixed_td
;
1184 cab_LONG fixed_bl
, fixed_bd
;
1185 cab_LONG i
; /* temporary variable */
1191 for(i
= 0; i
< 144; i
++)
1197 for(; i
< 288; i
++) /* make a complete, but wrong code set */
1200 if((i
= fdi_Ziphuft_build(l
, 288, 257, Zipcplens
, Zipcplext
, &fixed_tl
, &fixed_bl
, decomp_state
)))
1203 /* distance table */
1204 for(i
= 0; i
< 30; i
++) /* make an incomplete code set */
1207 if((i
= fdi_Ziphuft_build(l
, 30, 0, Zipcpdist
, Zipcpdext
, &fixed_td
, &fixed_bd
, decomp_state
)) > 1)
1209 fdi_Ziphuft_free(CAB(fdi
), fixed_tl
);
1213 /* decompress until an end-of-block code */
1214 i
= fdi_Zipinflate_codes(fixed_tl
, fixed_td
, fixed_bl
, fixed_bd
, decomp_state
);
1216 fdi_Ziphuft_free(CAB(fdi
), fixed_td
);
1217 fdi_Ziphuft_free(CAB(fdi
), fixed_tl
);
1221 /**************************************************************
1222 * fdi_Zipinflate_dynamic (internal)
1224 static cab_LONG
fdi_Zipinflate_dynamic(fdi_decomp_state
*decomp_state
)
1225 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1227 cab_LONG i
; /* temporary variables */
1230 cab_ULONG l
; /* last length */
1231 cab_ULONG m
; /* mask for bit lengths table */
1232 cab_ULONG n
; /* number of lengths to get */
1233 struct Ziphuft
*tl
; /* literal/length code table */
1234 struct Ziphuft
*td
; /* distance code table */
1235 cab_LONG bl
; /* lookup bits for tl */
1236 cab_LONG bd
; /* lookup bits for td */
1237 cab_ULONG nb
; /* number of bit length codes */
1238 cab_ULONG nl
; /* number of literal/length codes */
1239 cab_ULONG nd
; /* number of distance codes */
1240 register cab_ULONG b
; /* bit buffer */
1241 register cab_ULONG k
; /* number of bits in bit buffer */
1243 /* make local bit buffer */
1248 /* read in table lengths */
1250 nl
= 257 + (b
& 0x1f); /* number of literal/length codes */
1253 nd
= 1 + (b
& 0x1f); /* number of distance codes */
1256 nb
= 4 + (b
& 0xf); /* number of bit length codes */
1258 if(nl
> 288 || nd
> 32)
1259 return 1; /* bad lengths */
1261 /* read in bit-length-code lengths */
1262 for(j
= 0; j
< nb
; j
++)
1265 ll
[Zipborder
[j
]] = b
& 7;
1269 ll
[Zipborder
[j
]] = 0;
1271 /* build decoding table for trees--single level, 7 bit lookup */
1273 if((i
= fdi_Ziphuft_build(ll
, 19, 19, NULL
, NULL
, &tl
, &bl
, decomp_state
)) != 0)
1276 fdi_Ziphuft_free(CAB(fdi
), tl
);
1277 return i
; /* incomplete code set */
1280 /* read in literal and distance code lengths */
1284 while((cab_ULONG
)i
< n
)
1286 ZIPNEEDBITS((cab_ULONG
)bl
)
1287 j
= (td
= tl
+ (b
& m
))->b
;
1290 if (j
< 16) /* length of code in bits (0..15) */
1291 ll
[i
++] = l
= j
; /* save last length in l */
1292 else if (j
== 16) /* repeat last length 3 to 6 times */
1297 if((cab_ULONG
)i
+ j
> n
)
1302 else if (j
== 17) /* 3 to 10 zero length codes */
1307 if ((cab_ULONG
)i
+ j
> n
)
1313 else /* j == 18: 11 to 138 zero length codes */
1316 j
= 11 + (b
& 0x7f);
1318 if ((cab_ULONG
)i
+ j
> n
)
1326 /* free decoding table for trees */
1327 fdi_Ziphuft_free(CAB(fdi
), tl
);
1329 /* restore the global bit buffer */
1333 /* build the decoding tables for literal/length and distance codes */
1335 if((i
= fdi_Ziphuft_build(ll
, nl
, 257, Zipcplens
, Zipcplext
, &tl
, &bl
, decomp_state
)) != 0)
1338 fdi_Ziphuft_free(CAB(fdi
), tl
);
1339 return i
; /* incomplete code set */
1342 fdi_Ziphuft_build(ll
+ nl
, nd
, 0, Zipcpdist
, Zipcpdext
, &td
, &bd
, decomp_state
);
1344 /* decompress until an end-of-block code */
1345 if(fdi_Zipinflate_codes(tl
, td
, bl
, bd
, decomp_state
))
1348 /* free the decoding tables, return */
1349 fdi_Ziphuft_free(CAB(fdi
), tl
);
1350 fdi_Ziphuft_free(CAB(fdi
), td
);
1354 /*****************************************************
1355 * fdi_Zipinflate_block (internal)
1357 static cab_LONG
fdi_Zipinflate_block(cab_LONG
*e
, fdi_decomp_state
*decomp_state
) /* e == last block flag */
1358 { /* decompress an inflated block */
1359 cab_ULONG t
; /* block type */
1360 register cab_ULONG b
; /* bit buffer */
1361 register cab_ULONG k
; /* number of bits in bit buffer */
1363 /* make local bit buffer */
1367 /* read in last block bit */
1369 *e
= (cab_LONG
)b
& 1;
1372 /* read in block type */
1377 /* restore the global bit buffer */
1381 /* inflate that block type */
1383 return fdi_Zipinflate_dynamic(decomp_state
);
1385 return fdi_Zipinflate_stored(decomp_state
);
1387 return fdi_Zipinflate_fixed(decomp_state
);
1388 /* bad block type */
1392 /****************************************************
1393 * ZIPfdi_decomp(internal)
1395 static int ZIPfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
1397 cab_LONG e
; /* last block flag */
1399 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1401 ZIP(inpos
) = CAB(inbuf
);
1402 ZIP(bb
) = ZIP(bk
) = ZIP(window_posn
) = 0;
1403 if(outlen
> ZIPWSIZE
)
1404 return DECR_DATAFORMAT
;
1406 /* CK = Chris Kirmse, official Microsoft purloiner */
1407 if(ZIP(inpos
)[0] != 0x43 || ZIP(inpos
)[1] != 0x4B)
1408 return DECR_ILLEGALDATA
;
1412 if(fdi_Zipinflate_block(&e
, decomp_state
))
1413 return DECR_ILLEGALDATA
;
1416 /* return success */
1420 /*******************************************************************
1421 * QTMfdi_decomp(internal)
1423 static int QTMfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
1425 cab_UBYTE
*inpos
= CAB(inbuf
);
1426 cab_UBYTE
*window
= QTM(window
);
1427 cab_UBYTE
*runsrc
, *rundest
;
1428 cab_ULONG window_posn
= QTM(window_posn
);
1429 cab_ULONG window_size
= QTM(window_size
);
1431 /* used by bitstream macros */
1432 register int bitsleft
, bitrun
, bitsneed
;
1433 register cab_ULONG bitbuf
;
1435 /* used by GET_SYMBOL */
1440 int extra
, togo
= outlen
, match_length
= 0, copy_length
;
1441 cab_UBYTE selector
, sym
;
1442 cab_ULONG match_offset
= 0;
1444 cab_UWORD H
= 0xFFFF, L
= 0, C
;
1446 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1448 /* read initial value of C */
1452 /* apply 2^x-1 mask */
1453 window_posn
&= window_size
- 1;
1454 /* runs can't straddle the window wraparound */
1455 if ((window_posn
+ togo
) > window_size
) {
1456 TRACE("straddled run\n");
1457 return DECR_DATAFORMAT
;
1461 GET_SYMBOL(model7
, selector
);
1464 GET_SYMBOL(model00
, sym
); window
[window_posn
++] = sym
; togo
--;
1467 GET_SYMBOL(model40
, sym
); window
[window_posn
++] = sym
; togo
--;
1470 GET_SYMBOL(model80
, sym
); window
[window_posn
++] = sym
; togo
--;
1473 GET_SYMBOL(modelC0
, sym
); window
[window_posn
++] = sym
; togo
--;
1477 /* selector 4 = fixed length of 3 */
1478 GET_SYMBOL(model4
, sym
);
1479 Q_READ_BITS(extra
, CAB(q_extra_bits
)[sym
]);
1480 match_offset
= CAB(q_position_base
)[sym
] + extra
+ 1;
1485 /* selector 5 = fixed length of 4 */
1486 GET_SYMBOL(model5
, sym
);
1487 Q_READ_BITS(extra
, CAB(q_extra_bits
)[sym
]);
1488 match_offset
= CAB(q_position_base
)[sym
] + extra
+ 1;
1493 /* selector 6 = variable length */
1494 GET_SYMBOL(model6len
, sym
);
1495 Q_READ_BITS(extra
, CAB(q_length_extra
)[sym
]);
1496 match_length
= CAB(q_length_base
)[sym
] + extra
+ 5;
1497 GET_SYMBOL(model6pos
, sym
);
1498 Q_READ_BITS(extra
, CAB(q_extra_bits
)[sym
]);
1499 match_offset
= CAB(q_position_base
)[sym
] + extra
+ 1;
1503 TRACE("Selector is bogus\n");
1504 return DECR_ILLEGALDATA
;
1507 /* if this is a match */
1508 if (selector
>= 4) {
1509 rundest
= window
+ window_posn
;
1510 togo
-= match_length
;
1512 /* copy any wrapped around source data */
1513 if (window_posn
>= match_offset
) {
1515 runsrc
= rundest
- match_offset
;
1517 runsrc
= rundest
+ (window_size
- match_offset
);
1518 copy_length
= match_offset
- window_posn
;
1519 if (copy_length
< match_length
) {
1520 match_length
-= copy_length
;
1521 window_posn
+= copy_length
;
1522 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1526 window_posn
+= match_length
;
1528 /* copy match data - no worries about destination wraps */
1529 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1531 } /* while (togo > 0) */
1534 TRACE("Frame overflow, this_run = %d\n", togo
);
1535 return DECR_ILLEGALDATA
;
1538 memcpy(CAB(outbuf
), window
+ ((!window_posn
) ? window_size
: window_posn
) -
1541 QTM(window_posn
) = window_posn
;
1545 /************************************************************
1546 * fdi_lzx_read_lens (internal)
1548 static int fdi_lzx_read_lens(cab_UBYTE
*lens
, cab_ULONG first
, cab_ULONG last
, struct lzx_bits
*lb
,
1549 fdi_decomp_state
*decomp_state
) {
1553 register cab_ULONG bitbuf
= lb
->bb
;
1554 register int bitsleft
= lb
->bl
;
1555 cab_UBYTE
*inpos
= lb
->ip
;
1558 for (x
= 0; x
< 20; x
++) {
1560 LENTABLE(PRETREE
)[x
] = y
;
1562 BUILD_TABLE(PRETREE
);
1564 for (x
= first
; x
< last
; ) {
1565 READ_HUFFSYM(PRETREE
, z
);
1567 READ_BITS(y
, 4); y
+= 4;
1568 while (y
--) lens
[x
++] = 0;
1571 READ_BITS(y
, 5); y
+= 20;
1572 while (y
--) lens
[x
++] = 0;
1575 READ_BITS(y
, 1); y
+= 4;
1576 READ_HUFFSYM(PRETREE
, z
);
1577 z
= lens
[x
] - z
; if (z
< 0) z
+= 17;
1578 while (y
--) lens
[x
++] = z
;
1581 z
= lens
[x
] - z
; if (z
< 0) z
+= 17;
1592 /*******************************************************
1593 * LZXfdi_decomp(internal)
1595 static int LZXfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
) {
1596 cab_UBYTE
*inpos
= CAB(inbuf
);
1597 const cab_UBYTE
*endinp
= inpos
+ inlen
;
1598 cab_UBYTE
*window
= LZX(window
);
1599 cab_UBYTE
*runsrc
, *rundest
;
1600 cab_UWORD
*hufftbl
; /* used in READ_HUFFSYM macro as chosen decoding table */
1602 cab_ULONG window_posn
= LZX(window_posn
);
1603 cab_ULONG window_size
= LZX(window_size
);
1604 cab_ULONG R0
= LZX(R0
);
1605 cab_ULONG R1
= LZX(R1
);
1606 cab_ULONG R2
= LZX(R2
);
1608 register cab_ULONG bitbuf
;
1609 register int bitsleft
;
1610 cab_ULONG match_offset
, i
,j
,k
; /* ijk used in READ_HUFFSYM macro */
1611 struct lzx_bits lb
; /* used in READ_LENGTHS macro */
1613 int togo
= outlen
, this_run
, main_element
, aligned_bits
;
1614 int match_length
, copy_length
, length_footer
, extra
, verbatim_bits
;
1616 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1620 /* read header if necessary */
1621 if (!LZX(header_read
)) {
1623 READ_BITS(k
, 1); if (k
) { READ_BITS(i
,16); READ_BITS(j
,16); }
1624 LZX(intel_filesize
) = (i
<< 16) | j
; /* or 0 if not encoded */
1625 LZX(header_read
) = 1;
1628 /* main decoding loop */
1630 /* last block finished, new block expected */
1631 if (LZX(block_remaining
) == 0) {
1632 if (LZX(block_type
) == LZX_BLOCKTYPE_UNCOMPRESSED
) {
1633 if (LZX(block_length
) & 1) inpos
++; /* realign bitstream to word */
1637 READ_BITS(LZX(block_type
), 3);
1640 LZX(block_remaining
) = LZX(block_length
) = (i
<< 8) | j
;
1642 switch (LZX(block_type
)) {
1643 case LZX_BLOCKTYPE_ALIGNED
:
1644 for (i
= 0; i
< 8; i
++) { READ_BITS(j
, 3); LENTABLE(ALIGNED
)[i
] = j
; }
1645 BUILD_TABLE(ALIGNED
);
1646 /* rest of aligned header is same as verbatim */
1648 case LZX_BLOCKTYPE_VERBATIM
:
1649 READ_LENGTHS(MAINTREE
, 0, 256, fdi_lzx_read_lens
);
1650 READ_LENGTHS(MAINTREE
, 256, LZX(main_elements
), fdi_lzx_read_lens
);
1651 BUILD_TABLE(MAINTREE
);
1652 if (LENTABLE(MAINTREE
)[0xE8] != 0) LZX(intel_started
) = 1;
1654 READ_LENGTHS(LENGTH
, 0, LZX_NUM_SECONDARY_LENGTHS
, fdi_lzx_read_lens
);
1655 BUILD_TABLE(LENGTH
);
1658 case LZX_BLOCKTYPE_UNCOMPRESSED
:
1659 LZX(intel_started
) = 1; /* because we can't assume otherwise */
1660 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1661 if (bitsleft
> 16) inpos
-= 2; /* and align the bitstream! */
1662 R0
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1663 R1
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1664 R2
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1668 return DECR_ILLEGALDATA
;
1672 /* buffer exhaustion check */
1673 if (inpos
> endinp
) {
1674 /* it's possible to have a file where the next run is less than
1675 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1676 * in building the tables will exhaust the buffer, so we should
1677 * allow for this, but not allow those accidentally read bits to
1678 * be used (so we check that there are at least 16 bits
1679 * remaining - in this boundary case they aren't really part of
1680 * the compressed data)
1682 if (inpos
> (endinp
+2) || bitsleft
< 16) return DECR_ILLEGALDATA
;
1685 while ((this_run
= LZX(block_remaining
)) > 0 && togo
> 0) {
1686 if (this_run
> togo
) this_run
= togo
;
1688 LZX(block_remaining
) -= this_run
;
1690 /* apply 2^x-1 mask */
1691 window_posn
&= window_size
- 1;
1692 /* runs can't straddle the window wraparound */
1693 if ((window_posn
+ this_run
) > window_size
)
1694 return DECR_DATAFORMAT
;
1696 switch (LZX(block_type
)) {
1698 case LZX_BLOCKTYPE_VERBATIM
:
1699 while (this_run
> 0) {
1700 READ_HUFFSYM(MAINTREE
, main_element
);
1702 if (main_element
< LZX_NUM_CHARS
) {
1703 /* literal: 0 to LZX_NUM_CHARS-1 */
1704 window
[window_posn
++] = main_element
;
1708 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1709 main_element
-= LZX_NUM_CHARS
;
1711 match_length
= main_element
& LZX_NUM_PRIMARY_LENGTHS
;
1712 if (match_length
== LZX_NUM_PRIMARY_LENGTHS
) {
1713 READ_HUFFSYM(LENGTH
, length_footer
);
1714 match_length
+= length_footer
;
1716 match_length
+= LZX_MIN_MATCH
;
1718 match_offset
= main_element
>> 3;
1720 if (match_offset
> 2) {
1721 /* not repeated offset */
1722 if (match_offset
!= 3) {
1723 extra
= CAB(extra_bits
)[match_offset
];
1724 READ_BITS(verbatim_bits
, extra
);
1725 match_offset
= CAB(lzx_position_base
)[match_offset
]
1726 - 2 + verbatim_bits
;
1732 /* update repeated offset LRU queue */
1733 R2
= R1
; R1
= R0
; R0
= match_offset
;
1735 else if (match_offset
== 0) {
1738 else if (match_offset
== 1) {
1740 R1
= R0
; R0
= match_offset
;
1742 else /* match_offset == 2 */ {
1744 R2
= R0
; R0
= match_offset
;
1747 rundest
= window
+ window_posn
;
1748 this_run
-= match_length
;
1750 /* copy any wrapped around source data */
1751 if (window_posn
>= match_offset
) {
1753 runsrc
= rundest
- match_offset
;
1755 runsrc
= rundest
+ (window_size
- match_offset
);
1756 copy_length
= match_offset
- window_posn
;
1757 if (copy_length
< match_length
) {
1758 match_length
-= copy_length
;
1759 window_posn
+= copy_length
;
1760 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1764 window_posn
+= match_length
;
1766 /* copy match data - no worries about destination wraps */
1767 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1772 case LZX_BLOCKTYPE_ALIGNED
:
1773 while (this_run
> 0) {
1774 READ_HUFFSYM(MAINTREE
, main_element
);
1776 if (main_element
< LZX_NUM_CHARS
) {
1777 /* literal: 0 to LZX_NUM_CHARS-1 */
1778 window
[window_posn
++] = main_element
;
1782 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1783 main_element
-= LZX_NUM_CHARS
;
1785 match_length
= main_element
& LZX_NUM_PRIMARY_LENGTHS
;
1786 if (match_length
== LZX_NUM_PRIMARY_LENGTHS
) {
1787 READ_HUFFSYM(LENGTH
, length_footer
);
1788 match_length
+= length_footer
;
1790 match_length
+= LZX_MIN_MATCH
;
1792 match_offset
= main_element
>> 3;
1794 if (match_offset
> 2) {
1795 /* not repeated offset */
1796 extra
= CAB(extra_bits
)[match_offset
];
1797 match_offset
= CAB(lzx_position_base
)[match_offset
] - 2;
1799 /* verbatim and aligned bits */
1801 READ_BITS(verbatim_bits
, extra
);
1802 match_offset
+= (verbatim_bits
<< 3);
1803 READ_HUFFSYM(ALIGNED
, aligned_bits
);
1804 match_offset
+= aligned_bits
;
1806 else if (extra
== 3) {
1807 /* aligned bits only */
1808 READ_HUFFSYM(ALIGNED
, aligned_bits
);
1809 match_offset
+= aligned_bits
;
1811 else if (extra
> 0) { /* extra==1, extra==2 */
1812 /* verbatim bits only */
1813 READ_BITS(verbatim_bits
, extra
);
1814 match_offset
+= verbatim_bits
;
1816 else /* extra == 0 */ {
1821 /* update repeated offset LRU queue */
1822 R2
= R1
; R1
= R0
; R0
= match_offset
;
1824 else if (match_offset
== 0) {
1827 else if (match_offset
== 1) {
1829 R1
= R0
; R0
= match_offset
;
1831 else /* match_offset == 2 */ {
1833 R2
= R0
; R0
= match_offset
;
1836 rundest
= window
+ window_posn
;
1837 this_run
-= match_length
;
1839 /* copy any wrapped around source data */
1840 if (window_posn
>= match_offset
) {
1842 runsrc
= rundest
- match_offset
;
1844 runsrc
= rundest
+ (window_size
- match_offset
);
1845 copy_length
= match_offset
- window_posn
;
1846 if (copy_length
< match_length
) {
1847 match_length
-= copy_length
;
1848 window_posn
+= copy_length
;
1849 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1853 window_posn
+= match_length
;
1855 /* copy match data - no worries about destination wraps */
1856 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1861 case LZX_BLOCKTYPE_UNCOMPRESSED
:
1862 if ((inpos
+ this_run
) > endinp
) return DECR_ILLEGALDATA
;
1863 memcpy(window
+ window_posn
, inpos
, (size_t) this_run
);
1864 inpos
+= this_run
; window_posn
+= this_run
;
1868 return DECR_ILLEGALDATA
; /* might as well */
1874 if (togo
!= 0) return DECR_ILLEGALDATA
;
1875 memcpy(CAB(outbuf
), window
+ ((!window_posn
) ? window_size
: window_posn
) -
1876 outlen
, (size_t) outlen
);
1878 LZX(window_posn
) = window_posn
;
1883 /* intel E8 decoding */
1884 if ((LZX(frames_read
)++ < 32768) && LZX(intel_filesize
) != 0) {
1885 if (outlen
<= 6 || !LZX(intel_started
)) {
1886 LZX(intel_curpos
) += outlen
;
1889 cab_UBYTE
*data
= CAB(outbuf
);
1890 cab_UBYTE
*dataend
= data
+ outlen
- 10;
1891 cab_LONG curpos
= LZX(intel_curpos
);
1892 cab_LONG filesize
= LZX(intel_filesize
);
1893 cab_LONG abs_off
, rel_off
;
1895 LZX(intel_curpos
) = curpos
+ outlen
;
1897 while (data
< dataend
) {
1898 if (*data
++ != 0xE8) { curpos
++; continue; }
1899 abs_off
= data
[0] | (data
[1]<<8) | (data
[2]<<16) | (data
[3]<<24);
1900 if ((abs_off
>= -curpos
) && (abs_off
< filesize
)) {
1901 rel_off
= (abs_off
>= 0) ? abs_off
- curpos
: abs_off
+ filesize
;
1902 data
[0] = (cab_UBYTE
) rel_off
;
1903 data
[1] = (cab_UBYTE
) (rel_off
>> 8);
1904 data
[2] = (cab_UBYTE
) (rel_off
>> 16);
1905 data
[3] = (cab_UBYTE
) (rel_off
>> 24);
1915 /**********************************************************
1916 * fdi_decomp (internal)
1918 * Decompress the requested number of bytes. If savemode is zero,
1919 * do not save the output anywhere, just plow through blocks until we
1920 * reach the specified (uncompressed) distance from the starting point,
1921 * and remember the position of the cabfile pointer (and which cabfile)
1922 * after we are done; otherwise, save the data out to CAB(filehf),
1923 * decompressing the requested number of bytes and writing them out. This
1924 * is also where we jump to additional cabinets in the case of split
1925 * cab's, and provide (some of) the NEXT_CABINET notification semantics.
1927 static int fdi_decomp(const struct fdi_file
*fi
, int savemode
, fdi_decomp_state
*decomp_state
,
1928 char *pszCabPath
, PFNFDINOTIFY pfnfdin
, void *pvUser
)
1930 cab_ULONG bytes
= savemode
? fi
->length
: fi
->offset
- CAB(offset
);
1931 cab_UBYTE buf
[cfdata_SIZEOF
], *data
;
1932 cab_UWORD inlen
, len
, outlen
, cando
;
1935 fdi_decomp_state
*cab
= (savemode
&& CAB(decomp_cab
)) ? CAB(decomp_cab
) : decomp_state
;
1937 TRACE("(fi == ^%p, savemode == %d, bytes == %d)\n", fi
, savemode
, bytes
);
1940 /* cando = the max number of bytes we can do */
1941 cando
= CAB(outlen
);
1942 if (cando
> bytes
) cando
= bytes
;
1945 if (cando
&& savemode
)
1946 CAB(fdi
)->write(CAB(filehf
), CAB(outpos
), cando
);
1948 CAB(outpos
) += cando
;
1949 CAB(outlen
) -= cando
;
1950 bytes
-= cando
; if (!bytes
) break;
1952 /* we only get here if we emptied the output buffer */
1954 /* read data header + data */
1956 while (outlen
== 0) {
1957 /* read the block header, skip the reserved part */
1958 if (CAB(fdi
)->read(cab
->cabhf
, buf
, cfdata_SIZEOF
) != cfdata_SIZEOF
)
1961 if (CAB(fdi
)->seek(cab
->cabhf
, cab
->mii
.block_resv
, SEEK_CUR
) == -1)
1964 /* we shouldn't get blocks over CAB_INPUTMAX in size */
1965 data
= CAB(inbuf
) + inlen
;
1966 len
= EndGetI16(buf
+cfdata_CompressedSize
);
1968 if (inlen
> CAB_INPUTMAX
) return DECR_INPUT
;
1969 if (CAB(fdi
)->read(cab
->cabhf
, data
, len
) != len
)
1972 /* clear two bytes after read-in data */
1973 data
[len
+1] = data
[len
+2] = 0;
1975 /* perform checksum test on the block (if one is stored) */
1976 cksum
= EndGetI32(buf
+cfdata_CheckSum
);
1977 if (cksum
&& cksum
!= checksum(buf
+4, 4, checksum(data
, len
, 0)))
1978 return DECR_CHECKSUM
; /* checksum is wrong */
1980 outlen
= EndGetI16(buf
+cfdata_UncompressedSize
);
1982 /* outlen=0 means this block was the last contiguous part
1983 of a split block, continued in the next cabinet */
1985 int pathlen
, filenamelen
;
1987 char fullpath
[MAX_PATH
], userpath
[256];
1988 FDINOTIFICATION fdin
;
1989 FDICABINETINFO fdici
;
1990 char emptystring
= '\0';
1992 BOOL success
= FALSE
;
1993 struct fdi_folder
*fol
= NULL
, *linkfol
= NULL
;
1994 struct fdi_file
*file
= NULL
, *linkfile
= NULL
;
1998 /* set up the next decomp_state... */
2002 if (!cab
->mii
.hasnext
) return DECR_INPUT
;
2004 if (!((cab
->next
= CAB(fdi
)->alloc(sizeof(fdi_decomp_state
)))))
2005 return DECR_NOMEMORY
;
2007 ZeroMemory(cab
->next
, sizeof(fdi_decomp_state
));
2009 /* copy pszCabPath to userpath */
2010 ZeroMemory(userpath
, 256);
2011 pathlen
= pszCabPath
? strlen(pszCabPath
) : 0;
2013 if (pathlen
< 256) /* else we are in a weird place... let's leave it blank and see if the user fixes it */
2014 strcpy(userpath
, pszCabPath
);
2017 /* initial fdintNEXT_CABINET notification */
2018 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2019 fdin
.psz1
= cab
->mii
.nextname
? cab
->mii
.nextname
: &emptystring
;
2020 fdin
.psz2
= cab
->mii
.nextinfo
? cab
->mii
.nextinfo
: &emptystring
;
2021 fdin
.psz3
= userpath
;
2022 fdin
.fdie
= FDIERROR_NONE
;
2025 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2029 pathlen
= strlen(userpath
);
2030 filenamelen
= cab
->mii
.nextname
? strlen(cab
->mii
.nextname
) : 0;
2032 /* slight overestimation here to save CPU cycles in the developer's brain */
2033 if ((pathlen
+ filenamelen
+ 3) > MAX_PATH
) {
2034 ERR("MAX_PATH exceeded.\n");
2035 return DECR_ILLEGALDATA
;
2038 /* paste the path and filename together */
2041 strcpy(fullpath
, userpath
);
2042 if (fullpath
[pathlen
- 1] != '\\')
2043 strcat(fullpath
, "\\");
2046 strcat(fullpath
, cab
->mii
.nextname
);
2048 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath
));
2050 /* try to get a handle to the cabfile */
2051 cabhf
= CAB(fdi
)->open(fullpath
, _O_RDONLY
|_O_BINARY
, _S_IREAD
| _S_IWRITE
);
2053 /* no file. allow the user to try again */
2054 fdin
.fdie
= FDIERROR_CABINET_NOT_FOUND
;
2055 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2060 ERR("PFDI_OPEN returned zero for %s.\n", fullpath
);
2061 fdin
.fdie
= FDIERROR_CABINET_NOT_FOUND
;
2062 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2066 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2067 if (!FDI_read_entries(CAB(fdi
), cabhf
, &fdici
, &(cab
->next
->mii
))) {
2068 WARN("FDIIsCabinet failed.\n");
2069 CAB(fdi
)->close(cabhf
);
2070 fdin
.fdie
= FDIERROR_NOT_A_CABINET
;
2071 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2075 if ((fdici
.setID
!= cab
->setID
) || (fdici
.iCabinet
!= (cab
->iCabinet
+ 1))) {
2076 WARN("Wrong Cabinet.\n");
2077 CAB(fdi
)->close(cabhf
);
2078 fdin
.fdie
= FDIERROR_WRONG_CABINET
;
2079 if (((*pfnfdin
)(fdintNEXT_CABINET
, &fdin
))) return DECR_USERABORT
;
2087 /* cabinet notification */
2088 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2089 fdin
.setID
= fdici
.setID
;
2090 fdin
.iCabinet
= fdici
.iCabinet
;
2092 fdin
.psz1
= (cab
->next
->mii
.nextname
) ? cab
->next
->mii
.nextname
: &emptystring
;
2093 fdin
.psz2
= (cab
->next
->mii
.nextinfo
) ? cab
->next
->mii
.nextinfo
: &emptystring
;
2094 fdin
.psz3
= pszCabPath
;
2096 if (((*pfnfdin
)(fdintCABINET_INFO
, &fdin
))) return DECR_USERABORT
;
2098 cab
->next
->setID
= fdici
.setID
;
2099 cab
->next
->iCabinet
= fdici
.iCabinet
;
2100 cab
->next
->fdi
= CAB(fdi
);
2101 cab
->next
->filehf
= CAB(filehf
);
2102 cab
->next
->cabhf
= cabhf
;
2103 cab
->next
->decompress
= CAB(decompress
); /* crude, but unused anyhow */
2105 cab
= cab
->next
; /* advance to the next cabinet */
2108 for (i
= 0; i
< fdici
.cFolders
; i
++) {
2109 if (CAB(fdi
)->read(cab
->cabhf
, buf2
, cffold_SIZEOF
) != cffold_SIZEOF
)
2112 if (cab
->mii
.folder_resv
> 0)
2113 CAB(fdi
)->seek(cab
->cabhf
, cab
->mii
.folder_resv
, SEEK_CUR
);
2115 fol
= CAB(fdi
)->alloc(sizeof(struct fdi_folder
));
2117 ERR("out of memory!\n");
2118 return DECR_NOMEMORY
;
2120 ZeroMemory(fol
, sizeof(struct fdi_folder
));
2121 if (!(cab
->firstfol
)) cab
->firstfol
= fol
;
2123 fol
->offset
= (cab_off_t
) EndGetI32(buf2
+cffold_DataOffset
);
2124 fol
->num_blocks
= EndGetI16(buf2
+cffold_NumBlocks
);
2125 fol
->comp_type
= EndGetI16(buf2
+cffold_CompType
);
2128 linkfol
->next
= fol
;
2133 for (i
= 0; i
< fdici
.cFiles
; i
++) {
2134 if (CAB(fdi
)->read(cab
->cabhf
, buf2
, cffile_SIZEOF
) != cffile_SIZEOF
)
2137 file
= CAB(fdi
)->alloc(sizeof(struct fdi_file
));
2139 ERR("out of memory!\n");
2140 return DECR_NOMEMORY
;
2142 ZeroMemory(file
, sizeof(struct fdi_file
));
2143 if (!(cab
->firstfile
)) cab
->firstfile
= file
;
2145 file
->length
= EndGetI32(buf2
+cffile_UncompressedSize
);
2146 file
->offset
= EndGetI32(buf2
+cffile_FolderOffset
);
2147 file
->index
= EndGetI16(buf2
+cffile_FolderIndex
);
2148 file
->time
= EndGetI16(buf2
+cffile_Time
);
2149 file
->date
= EndGetI16(buf2
+cffile_Date
);
2150 file
->attribs
= EndGetI16(buf2
+cffile_Attribs
);
2151 file
->filename
= FDI_read_string(CAB(fdi
), cab
->cabhf
, fdici
.cbCabinet
);
2153 if (!file
->filename
) return DECR_INPUT
;
2156 linkfile
->next
= file
;
2161 cab
= cab
->next
; /* advance to the next cabinet */
2163 /* iterate files -- if we encounter the continued file, process it --
2164 otherwise, jump to the label above and keep looking */
2166 for (file
= cab
->firstfile
; (file
); file
= file
->next
) {
2167 if ((file
->index
& cffileCONTINUED_FROM_PREV
) == cffileCONTINUED_FROM_PREV
) {
2168 /* check to ensure a real match */
2169 if (lstrcmpiA(fi
->filename
, file
->filename
) == 0) {
2171 if (CAB(fdi
)->seek(cab
->cabhf
, cab
->firstfol
->offset
, SEEK_SET
) == -1)
2177 if (!success
) goto tryanothercab
; /* FIXME: shouldn't this trigger
2178 "Wrong Cabinet" notification? */
2182 /* decompress block */
2183 if ((err
= CAB(decompress
)(inlen
, outlen
, decomp_state
)))
2185 CAB(outlen
) = outlen
;
2186 CAB(outpos
) = CAB(outbuf
);
2189 CAB(decomp_cab
) = cab
;
2193 static void free_decompression_temps(FDI_Int
*fdi
, const struct fdi_folder
*fol
,
2194 fdi_decomp_state
*decomp_state
)
2196 switch (fol
->comp_type
& cffoldCOMPTYPE_MASK
) {
2197 case cffoldCOMPTYPE_LZX
:
2199 fdi
->free(LZX(window
));
2203 case cffoldCOMPTYPE_QUANTUM
:
2205 fdi
->free(QTM(window
));
2212 static void free_decompression_mem(FDI_Int
*fdi
, fdi_decomp_state
*decomp_state
)
2214 struct fdi_folder
*fol
;
2215 while (decomp_state
) {
2216 fdi_decomp_state
*prev_fds
;
2218 fdi
->close(CAB(cabhf
));
2220 /* free the storage remembered by mii */
2221 if (CAB(mii
).nextname
) fdi
->free(CAB(mii
).nextname
);
2222 if (CAB(mii
).nextinfo
) fdi
->free(CAB(mii
).nextinfo
);
2223 if (CAB(mii
).prevname
) fdi
->free(CAB(mii
).prevname
);
2224 if (CAB(mii
).previnfo
) fdi
->free(CAB(mii
).previnfo
);
2226 while (CAB(firstfol
)) {
2227 fol
= CAB(firstfol
);
2228 CAB(firstfol
) = CAB(firstfol
)->next
;
2231 while (CAB(firstfile
)) {
2232 struct fdi_file
*file
= CAB(firstfile
);
2233 if (file
->filename
) fdi
->free(file
->filename
);
2234 CAB(firstfile
) = CAB(firstfile
)->next
;
2237 prev_fds
= decomp_state
;
2238 decomp_state
= CAB(next
);
2239 fdi
->free(prev_fds
);
2243 /***********************************************************************
2244 * FDICopy (CABINET.22)
2246 * Iterates through the files in the Cabinet file indicated by name and
2247 * file-location. May chain forward to additional cabinets (typically
2248 * only one) if files which begin in this Cabinet are continued in another
2249 * cabinet. For each file which is partially contained in this cabinet,
2250 * and partially contained in a prior cabinet, provides fdintPARTIAL_FILE
2251 * notification to the pfnfdin callback. For each file which begins in
2252 * this cabinet, fdintCOPY_FILE notification is provided to the pfnfdin
2253 * callback, and the file is optionally decompressed and saved to disk.
2254 * Notification is not provided for files which are not at least partially
2255 * contained in the specified cabinet file.
2257 * See below for a thorough explanation of the various notification
2261 * hfdi [I] An HFDI from FDICreate
2262 * pszCabinet [I] C-style string containing the filename of the cabinet
2263 * pszCabPath [I] C-style string containing the file path of the cabinet
2264 * flags [I] "Decoder parameters". Ignored. Suggested value: 0.
2265 * pfnfdin [I] Pointer to a notification function. See CALLBACKS below.
2266 * pfnfdid [I] Pointer to a decryption function. Ignored. Suggested
2268 * pvUser [I] arbitrary void * value which is passed to callbacks.
2271 * TRUE if successful.
2272 * FALSE if unsuccessful (error information is provided in the ERF structure
2273 * associated with the provided decompression handle by FDICreate).
2277 * Two pointers to callback functions are provided as parameters to FDICopy:
2278 * pfnfdin(of type PFNFDINOTIFY), and pfnfdid (of type PFNFDIDECRYPT). These
2279 * types are as follows:
2281 * typedef INT_PTR (__cdecl *PFNFDINOTIFY) ( FDINOTIFICATIONTYPE fdint,
2282 * PFDINOTIFICATION pfdin );
2284 * typedef int (__cdecl *PFNFDIDECRYPT) ( PFDIDECRYPT pfdid );
2286 * You can create functions of this type using the FNFDINOTIFY() and
2287 * FNFDIDECRYPT() macros, respectively. For example:
2289 * FNFDINOTIFY(mycallback) {
2290 * / * use variables fdint and pfdin to process notification * /
2293 * The second callback, which could be used for decrypting encrypted data,
2294 * is not used at all.
2296 * Each notification informs the user of some event which has occurred during
2297 * decompression of the cabinet file; each notification is also an opportunity
2298 * for the callee to abort decompression. The information provided to the
2299 * callback and the meaning of the callback's return value vary drastically
2300 * across the various types of notification. The type of notification is the
2301 * fdint parameter; all other information is provided to the callback in
2302 * notification-specific parts of the FDINOTIFICATION structure pointed to by
2303 * pfdin. The only part of that structure which is assigned for every callback
2304 * is the pv element, which contains the arbitrary value which was passed to
2305 * FDICopy in the pvUser argument (psz1 is also used each time, but its meaning
2306 * is highly dependent on fdint).
2308 * If you encounter unknown notifications, you should return zero if you want
2309 * decompression to continue (or -1 to abort). All strings used in the
2310 * callbacks are regular C-style strings. Detailed descriptions of each
2311 * notification type follow:
2313 * fdintCABINET_INFO:
2315 * This is the first notification provided after calling FDICopy, and provides
2316 * the user with various information about the cabinet. Note that this is
2317 * called for each cabinet FDICopy opens, not just the first one. In the
2318 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2319 * next cabinet file in the set after the one just loaded (if any), psz2
2320 * contains a pointer to the name or "info" of the next disk, psz3
2321 * contains a pointer to the file-path of the current cabinet, setID
2322 * contains an arbitrary constant associated with this set of cabinet files,
2323 * and iCabinet contains the numerical index of the current cabinet within
2324 * that set. Return zero, or -1 to abort.
2326 * fdintPARTIAL_FILE:
2328 * This notification is provided when FDICopy encounters a part of a file
2329 * contained in this cabinet which is missing its beginning. Files can be
2330 * split across cabinets, so this is not necessarily an abnormality; it just
2331 * means that the file in question begins in another cabinet. No file
2332 * corresponding to this notification is extracted from the cabinet. In the
2333 * structure pointed to by pfdin, psz1 contains a pointer to the name of the
2334 * partial file, psz2 contains a pointer to the file name of the cabinet in
2335 * which this file begins, and psz3 contains a pointer to the disk name or
2336 * "info" of the cabinet where the file begins. Return zero, or -1 to abort.
2340 * This notification is provided when FDICopy encounters a file which starts
2341 * in the cabinet file, provided to FDICopy in pszCabinet. (FDICopy will not
2342 * look for files in cabinets after the first one). One notification will be
2343 * sent for each such file, before the file is decompressed. By returning
2344 * zero, the callback can instruct FDICopy to skip the file. In the structure
2345 * pointed to by pfdin, psz1 contains a pointer to the file's name, cb contains
2346 * the size of the file (uncompressed), attribs contains the file attributes,
2347 * and date and time contain the date and time of the file. attributes, date,
2348 * and time are of the 16-bit ms-dos variety. Return -1 to abort decompression
2349 * for the entire cabinet, 0 to skip just this file but continue scanning the
2350 * cabinet for more files, or an FDIClose()-compatible file-handle.
2352 * fdintCLOSE_FILE_INFO:
2354 * This notification is important, don't forget to implement it. This
2355 * notification indicates that a file has been successfully uncompressed and
2356 * written to disk. Upon receipt of this notification, the callee is expected
2357 * to close the file handle, to set the attributes and date/time of the
2358 * closed file, and possibly to execute the file. In the structure pointed to
2359 * by pfdin, psz1 contains a pointer to the name of the file, hf will be the
2360 * open file handle (close it), cb contains 1 or zero, indicating respectively
2361 * that the callee should or should not execute the file, and date, time
2362 * and attributes will be set as in fdintCOPY_FILE. Bizarrely, the Cabinet SDK
2363 * specifies that _A_EXEC will be xor'ed out of attributes! wine does not do
2364 * do so. Return TRUE, or FALSE to abort decompression.
2366 * fdintNEXT_CABINET:
2368 * This notification is called when FDICopy must load in another cabinet. This
2369 * can occur when a file's data is "split" across multiple cabinets. The
2370 * callee has the opportunity to request that FDICopy look in a different file
2371 * path for the specified cabinet file, by writing that data into a provided
2372 * buffer (see below for more information). This notification will be received
2373 * more than once per-cabinet in the instance that FDICopy failed to find a
2374 * valid cabinet at the location specified by the first per-cabinet
2375 * fdintNEXT_CABINET notification. In such instances, the fdie element of the
2376 * structure pointed to by pfdin indicates the error which prevented FDICopy
2377 * from proceeding successfully. Return zero to indicate success, or -1 to
2378 * indicate failure and abort FDICopy.
2380 * Upon receipt of this notification, the structure pointed to by pfdin will
2381 * contain the following values: psz1 pointing to the name of the cabinet
2382 * which FDICopy is attempting to open, psz2 pointing to the name ("info") of
2383 * the next disk, psz3 pointing to the presumed file-location of the cabinet,
2384 * and fdie containing either FDIERROR_NONE, or one of the following:
2386 * FDIERROR_CABINET_NOT_FOUND, FDIERROR_NOT_A_CABINET,
2387 * FDIERROR_UNKNOWN_CABINET_VERSION, FDIERROR_CORRUPT_CABINET,
2388 * FDIERROR_BAD_COMPR_TYPE, FDIERROR_RESERVE_MISMATCH, and
2389 * FDIERROR_WRONG_CABINET.
2391 * The callee may choose to change the path where FDICopy will look for the
2392 * cabinet after this notification. To do so, the caller may write the new
2393 * pathname to the buffer pointed to by psz3, which is 256 characters in
2394 * length, including the terminating null character, before returning zero.
2398 * Undocumented and unimplemented in wine, this seems to be sent each time
2399 * a cabinet is opened, along with the fdintCABINET_INFO notification. It
2400 * probably has an interface similar to that of fdintCABINET_INFO; maybe this
2401 * provides information about the current cabinet instead of the next one....
2402 * this is just a guess, it has not been looked at closely.
2407 BOOL __cdecl
FDICopy(
2412 PFNFDINOTIFY pfnfdin
,
2413 PFNFDIDECRYPT pfnfdid
,
2416 FDICABINETINFO fdici
;
2417 FDINOTIFICATION fdin
;
2418 INT_PTR cabhf
, filehf
= 0;
2420 char fullpath
[MAX_PATH
];
2421 size_t pathlen
, filenamelen
;
2422 char emptystring
= '\0';
2424 struct fdi_folder
*fol
= NULL
, *linkfol
= NULL
;
2425 struct fdi_file
*file
= NULL
, *linkfile
= NULL
;
2426 fdi_decomp_state
*decomp_state
;
2427 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
2429 TRACE("(hfdi == ^%p, pszCabinet == %s, pszCabPath == %s, flags == %x, "
2430 "pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
2431 hfdi
, debugstr_a(pszCabinet
), debugstr_a(pszCabPath
), flags
, pfnfdin
, pfnfdid
, pvUser
);
2433 if (!fdi
) return FALSE
;
2435 if (!(decomp_state
= fdi
->alloc(sizeof(fdi_decomp_state
))))
2437 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2440 ZeroMemory(decomp_state
, sizeof(fdi_decomp_state
));
2442 pathlen
= pszCabPath
? strlen(pszCabPath
) : 0;
2443 filenamelen
= pszCabinet
? strlen(pszCabinet
) : 0;
2445 /* slight overestimation here to save CPU cycles in the developer's brain */
2446 if ((pathlen
+ filenamelen
+ 3) > MAX_PATH
) {
2447 ERR("MAX_PATH exceeded.\n");
2448 fdi
->free(decomp_state
);
2449 set_error( fdi
, FDIERROR_CABINET_NOT_FOUND
, ERROR_FILE_NOT_FOUND
);
2453 /* paste the path and filename together */
2456 strcpy(fullpath
, pszCabPath
);
2458 strcat(fullpath
, pszCabinet
);
2460 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath
));
2462 /* get a handle to the cabfile */
2463 cabhf
= fdi
->open(fullpath
, _O_RDONLY
|_O_BINARY
, _S_IREAD
| _S_IWRITE
);
2465 fdi
->free(decomp_state
);
2466 set_error( fdi
, FDIERROR_CABINET_NOT_FOUND
, 0 );
2467 SetLastError(ERROR_FILE_NOT_FOUND
);
2471 /* check if it's really a cabfile. Note that this doesn't implement the bug */
2472 if (!FDI_read_entries(fdi
, cabhf
, &fdici
, &(CAB(mii
)))) {
2473 WARN("FDI_read_entries failed: %u\n", fdi
->perf
->erfOper
);
2474 fdi
->free(decomp_state
);
2479 /* cabinet notification */
2480 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2481 fdin
.setID
= fdici
.setID
;
2482 fdin
.iCabinet
= fdici
.iCabinet
;
2484 fdin
.psz1
= (CAB(mii
).nextname
) ? CAB(mii
).nextname
: &emptystring
;
2485 fdin
.psz2
= (CAB(mii
).nextinfo
) ? CAB(mii
).nextinfo
: &emptystring
;
2486 fdin
.psz3
= pszCabPath
;
2488 if (((*pfnfdin
)(fdintCABINET_INFO
, &fdin
))) {
2489 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2493 CAB(setID
) = fdici
.setID
;
2494 CAB(iCabinet
) = fdici
.iCabinet
;
2498 for (i
= 0; i
< fdici
.cFolders
; i
++) {
2499 if (fdi
->read(cabhf
, buf
, cffold_SIZEOF
) != cffold_SIZEOF
) {
2500 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2504 if (CAB(mii
).folder_resv
> 0)
2505 fdi
->seek(cabhf
, CAB(mii
).folder_resv
, SEEK_CUR
);
2507 fol
= fdi
->alloc(sizeof(struct fdi_folder
));
2509 ERR("out of memory!\n");
2510 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2513 ZeroMemory(fol
, sizeof(struct fdi_folder
));
2514 if (!CAB(firstfol
)) CAB(firstfol
) = fol
;
2516 fol
->offset
= (cab_off_t
) EndGetI32(buf
+cffold_DataOffset
);
2517 fol
->num_blocks
= EndGetI16(buf
+cffold_NumBlocks
);
2518 fol
->comp_type
= EndGetI16(buf
+cffold_CompType
);
2521 linkfol
->next
= fol
;
2526 for (i
= 0; i
< fdici
.cFiles
; i
++) {
2527 if (fdi
->read(cabhf
, buf
, cffile_SIZEOF
) != cffile_SIZEOF
) {
2528 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2532 file
= fdi
->alloc(sizeof(struct fdi_file
));
2534 ERR("out of memory!\n");
2535 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2538 ZeroMemory(file
, sizeof(struct fdi_file
));
2539 if (!CAB(firstfile
)) CAB(firstfile
) = file
;
2541 file
->length
= EndGetI32(buf
+cffile_UncompressedSize
);
2542 file
->offset
= EndGetI32(buf
+cffile_FolderOffset
);
2543 file
->index
= EndGetI16(buf
+cffile_FolderIndex
);
2544 file
->time
= EndGetI16(buf
+cffile_Time
);
2545 file
->date
= EndGetI16(buf
+cffile_Date
);
2546 file
->attribs
= EndGetI16(buf
+cffile_Attribs
);
2547 file
->filename
= FDI_read_string(fdi
, cabhf
, fdici
.cbCabinet
);
2549 if (!file
->filename
) {
2550 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2555 linkfile
->next
= file
;
2559 for (file
= CAB(firstfile
); (file
); file
= file
->next
) {
2562 * FIXME: This implementation keeps multiple cabinet files open at once
2563 * when encountering a split cabinet. It is a quirk of this implementation
2564 * that sometimes we decrypt the same block of data more than once, to find
2565 * the right starting point for a file, moving the file-pointer backwards.
2566 * If we kept a cache of certain file-pointer information, we could eliminate
2567 * that behavior... in fact I am not sure that the caching we already have
2568 * is not sufficient.
2570 * The current implementation seems to work fine in straightforward situations
2571 * where all the cabinet files needed for decryption are simultaneously
2572 * available. But presumably, the API is supposed to support cabinets which
2573 * are split across multiple CDROMS; we may need to change our implementation
2574 * to strictly serialize its file usage so that it opens only one cabinet
2575 * at a time. Some experimentation with Windows is needed to figure out the
2576 * precise semantics required. The relevant code is here and in fdi_decomp().
2579 /* partial-file notification */
2580 if ((file
->index
& cffileCONTINUED_FROM_PREV
) == cffileCONTINUED_FROM_PREV
) {
2582 * FIXME: Need to create a Cabinet with a single file spanning multiple files
2583 * and perform some tests to figure out the right behavior. The SDK says
2584 * FDICopy will notify the user of the filename and "disk name" (info) of
2585 * the cabinet where the spanning file /started/.
2587 * That would certainly be convenient for the API-user, who could abort,
2588 * everything (or parallelize, if that's allowed (it is in wine)), and call
2589 * FDICopy again with the provided filename, so as to avoid partial file
2590 * notification and successfully unpack. This task could be quite unpleasant
2591 * from wine's perspective: the information specifying the "start cabinet" for
2592 * a file is associated nowhere with the file header and is not to be found in
2593 * the cabinet header. We have only the index of the cabinet wherein the folder
2594 * begins, which contains the file. To find that cabinet, we must consider the
2595 * index of the current cabinet, and chain backwards, cabinet-by-cabinet (for
2596 * each cabinet refers to its "next" and "previous" cabinet only, like a linked
2599 * Bear in mind that, in the spirit of CABINET.DLL, we must assume that any
2600 * cabinet other than the active one might be at another filepath than the
2601 * current one, or on another CDROM. This could get rather dicey, especially
2602 * if we imagine parallelized access to the FDICopy API.
2604 * The current implementation punts -- it just returns the previous cabinet and
2605 * its info from the header of this cabinet. This provides the right answer in
2606 * 95% of the cases; it's worth checking if Microsoft cuts the same corner before
2609 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2611 fdin
.psz1
= (char *)file
->filename
;
2612 fdin
.psz2
= (CAB(mii
).prevname
) ? CAB(mii
).prevname
: &emptystring
;
2613 fdin
.psz3
= (CAB(mii
).previnfo
) ? CAB(mii
).previnfo
: &emptystring
;
2615 if (((*pfnfdin
)(fdintPARTIAL_FILE
, &fdin
))) {
2616 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2619 /* I don't think we are supposed to decompress partial files. This prevents it. */
2620 file
->oppressed
= TRUE
;
2622 if (file
->oppressed
) {
2625 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2627 fdin
.psz1
= (char *)file
->filename
;
2628 fdin
.cb
= file
->length
;
2629 fdin
.date
= file
->date
;
2630 fdin
.time
= file
->time
;
2631 fdin
.attribs
= file
->attribs
;
2632 if ((filehf
= ((*pfnfdin
)(fdintCOPY_FILE
, &fdin
))) == -1) {
2633 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2639 /* find the folder for this file if necc. */
2641 fol
= CAB(firstfol
);
2642 if ((file
->index
& cffileCONTINUED_TO_NEXT
) == cffileCONTINUED_TO_NEXT
) {
2643 /* pick the last folder */
2644 while (fol
->next
) fol
= fol
->next
;
2648 for (i2
= 0; (i2
< file
->index
); i2
++)
2649 if (fol
->next
) /* bug resistance, should always be true */
2655 cab_UWORD comptype
= fol
->comp_type
;
2656 int ct1
= comptype
& cffoldCOMPTYPE_MASK
;
2657 int ct2
= CAB(current
) ? (CAB(current
)->comp_type
& cffoldCOMPTYPE_MASK
) : 0;
2660 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file
->filename
));
2662 /* set up decomp_state */
2664 CAB(filehf
) = filehf
;
2666 /* Was there a change of folder? Compression type? Did we somehow go backwards? */
2667 if ((ct1
!= ct2
) || (CAB(current
) != fol
) || (file
->offset
< CAB(offset
))) {
2669 TRACE("Resetting folder for file %s.\n", debugstr_a(file
->filename
));
2671 /* free stuff for the old decompressor */
2673 case cffoldCOMPTYPE_LZX
:
2675 fdi
->free(LZX(window
));
2679 case cffoldCOMPTYPE_QUANTUM
:
2681 fdi
->free(QTM(window
));
2687 CAB(decomp_cab
) = NULL
;
2688 CAB(fdi
)->seek(CAB(cabhf
), fol
->offset
, SEEK_SET
);
2692 /* initialize the new decompressor */
2694 case cffoldCOMPTYPE_NONE
:
2695 CAB(decompress
) = NONEfdi_decomp
;
2697 case cffoldCOMPTYPE_MSZIP
:
2698 CAB(decompress
) = ZIPfdi_decomp
;
2700 case cffoldCOMPTYPE_QUANTUM
:
2701 CAB(decompress
) = QTMfdi_decomp
;
2702 err
= QTMfdi_init((comptype
>> 8) & 0x1f, (comptype
>> 4) & 0xF, decomp_state
);
2704 case cffoldCOMPTYPE_LZX
:
2705 CAB(decompress
) = LZXfdi_decomp
;
2706 err
= LZXfdi_init((comptype
>> 8) & 0x1f, decomp_state
);
2709 err
= DECR_DATAFORMAT
;
2719 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2722 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2726 if (file
->offset
> CAB(offset
)) {
2727 /* decode bytes and send them to /dev/null */
2728 switch (fdi_decomp(file
, 0, decomp_state
, pszCabPath
, pfnfdin
, pvUser
)) {
2731 case DECR_USERABORT
:
2732 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2735 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2738 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2741 CAB(offset
) = file
->offset
;
2744 /* now do the actual decompression */
2745 err
= fdi_decomp(file
, 1, decomp_state
, pszCabPath
, pfnfdin
, pvUser
);
2746 if (err
) CAB(current
) = NULL
; else CAB(offset
) += file
->length
;
2748 /* fdintCLOSE_FILE_INFO notification */
2749 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2751 fdin
.psz1
= (char *)file
->filename
;
2753 fdin
.cb
= (file
->attribs
& cffile_A_EXEC
) != 0; /* FIXME: is that right? */
2754 fdin
.date
= file
->date
;
2755 fdin
.time
= file
->time
;
2756 fdin
.attribs
= file
->attribs
; /* FIXME: filter _A_EXEC? */
2757 ((*pfnfdin
)(fdintCLOSE_FILE_INFO
, &fdin
));
2763 case DECR_USERABORT
:
2764 set_error( fdi
, FDIERROR_USER_ABORT
, 0 );
2767 set_error( fdi
, FDIERROR_ALLOC_FAIL
, ERROR_NOT_ENOUGH_MEMORY
);
2770 set_error( fdi
, FDIERROR_CORRUPT_CABINET
, 0 );
2776 if (fol
) free_decompression_temps(fdi
, fol
, decomp_state
);
2777 free_decompression_mem(fdi
, decomp_state
);
2781 bail_and_fail
: /* here we free ram before error returns */
2783 if (fol
) free_decompression_temps(fdi
, fol
, decomp_state
);
2785 if (filehf
) fdi
->close(filehf
);
2787 free_decompression_mem(fdi
, decomp_state
);
2792 /***********************************************************************
2793 * FDIDestroy (CABINET.23)
2795 * Frees a handle created by FDICreate. Do /not/ call this in the middle
2796 * of FDICopy. Only reason for failure would be an invalid handle.
2799 * hfdi [I] The HFDI to free
2805 BOOL __cdecl
FDIDestroy(HFDI hfdi
)
2807 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
2809 TRACE("(hfdi == ^%p)\n", hfdi
);
2810 if (!fdi
) return FALSE
;
2811 fdi
->magic
= 0; /* paranoia */
2816 /***********************************************************************
2817 * FDITruncateCabinet (CABINET.24)
2819 * Removes all folders of a cabinet file after and including the
2820 * specified folder number.
2823 * hfdi [I] Handle to the FDI context.
2824 * pszCabinetName [I] Filename of the cabinet.
2825 * iFolderToDelete [I] Index of the first folder to delete.
2832 * The PFNWRITE function supplied to FDICreate must truncate the
2833 * file at the current position if the number of bytes to write is 0.
2835 BOOL __cdecl
FDITruncateCabinet(
2837 char *pszCabinetName
,
2838 USHORT iFolderToDelete
)
2840 FDI_Int
*fdi
= get_fdi_ptr( hfdi
);
2842 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2843 hfdi
, debugstr_a(pszCabinetName
), iFolderToDelete
);
2845 if (!fdi
) return FALSE
;
2847 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);