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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * This is (or will be) a largely redundant reimplementation of the stuff in
24 * cabextract.c... it would theoretically be preferable to have only one, shared
25 * implementation, however there are semantic differences which may discourage efforts
26 * to unify the two. It should be possible, if awkward, to go back and reimplement
27 * cabextract.c using FDI (once the FDI implementation is complete, of course).
39 #include "msvcrt/fcntl.h" /* _O_.* */
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(cabinet
);
49 struct fdi_file
*next
; /* next file in sequence */
50 struct fdi_folder
*folder
; /* folder that contains this file */
51 LPCSTR filename
; /* output name of file */
52 int fh
; /* open file handle or NULL */
53 cab_ULONG length
; /* uncompressed length of file */
54 cab_ULONG offset
; /* uncompressed offset in folder */
55 cab_UWORD index
; /* magic index number of folder */
56 cab_UWORD time
, date
, attribs
; /* MS-DOS time/date/attributes */
57 BOOL oppressed
; /* never to be processed */
61 struct fdi_folder
*next
;
62 cab_off_t offset
[CAB_SPLITMAX
]; /* offset to data blocks (32 bit) */
63 cab_UWORD comp_type
; /* compression format/window size */
64 cab_ULONG comp_size
; /* compressed size of folder */
65 cab_UBYTE num_splits
; /* number of split blocks + 1 */
66 cab_UWORD num_blocks
; /* total number of blocks */
67 struct fdi_file
*contfile
; /* the first split file */
71 * ugh, well, this ended up being pretty damn silly...
72 * now that I've conceeded to build equivalent structures to struct cab.*,
73 * I should have just used those, or, better yet, unified the two... sue me.
74 * (Note to Microsoft: That's a joke. Please /don't/ actually sue me! -gmt).
75 * Nevertheless, I've come this far, it works, so I'm not gonna change it
79 typedef struct fdi_cds_fwd
{
80 void *hfdi
; /* the hfdi we are using */
81 int filehf
, cabhf
; /* file handle we are using */
82 struct fdi_folder
*current
; /* current folder we're extracting from */
84 cab_ULONG offset
; /* uncompressed offset within folder */
85 cab_UBYTE
*outpos
; /* (high level) start of data to use up */
86 cab_UWORD outlen
; /* (high level) amount of data to use up */
87 cab_UWORD split
; /* at which split in current folder? */
88 int (*decompress
)(int, int, struct fdi_cds_fwd
*); /* chosen compress fn */
89 cab_UBYTE inbuf
[CAB_INPUTMAX
+2]; /* +2 for lzx bitbuffer overflows! */
90 cab_UBYTE outbuf
[CAB_BLOCKMAX
];
96 struct fdi_folder
*firstfol
;
97 struct fdi_file
*firstfile
;
98 struct fdi_cds_fwd
*next
;
102 * this structure fills the gaps between what is available in a PFDICABINETINFO
103 * vs what is needed by FDICopy. Memory allocated for these becomes the responsibility
104 * of the caller to free. Yes, I am aware that this is totally, utterly inelegant.
107 char *prevname
, *previnfo
;
108 char *nextname
, *nextinfo
;
109 int folder_resv
, header_resv
;
110 cab_UBYTE block_resv
;
111 } MORE_ISCAB_INFO
, *PMORE_ISCAB_INFO
;
113 /***********************************************************************
114 * FDICreate (CABINET.20)
116 HFDI __cdecl
FDICreate(
129 TRACE("(pfnalloc == ^%p, pfnfree == ^%p, pfnopen == ^%p, pfnread == ^%p, pfnwrite == ^%p, \
130 pfnclose == ^%p, pfnseek == ^%p, cpuType == %d, perf == ^%p)\n",
131 pfnalloc
, pfnfree
, pfnopen
, pfnread
, pfnwrite
, pfnclose
, pfnseek
,
134 /* PONDERME: Certainly, we cannot tolerate a missing pfnalloc, as we call it just below.
135 pfnfree is tested as well, for symmetry. As for the rest, should we test these
136 too? In a vacuum, I would say yes... but does Windows care? If not, then, I guess,
138 if ((!pfnalloc
) || (!pfnfree
)) {
139 perf
->erfOper
= FDIERROR_NONE
;
140 perf
->erfType
= ERROR_BAD_ARGUMENTS
;
143 SetLastError(ERROR_BAD_ARGUMENTS
);
147 if (!((rv
= ((HFDI
) (*pfnalloc
)(sizeof(FDI_Int
)))))) {
148 perf
->erfOper
= FDIERROR_ALLOC_FAIL
;
149 perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
152 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
156 PFDI_INT(rv
)->FDI_Intmagic
= FDI_INT_MAGIC
;
157 PFDI_INT(rv
)->pfnalloc
= pfnalloc
;
158 PFDI_INT(rv
)->pfnfree
= pfnfree
;
159 PFDI_INT(rv
)->pfnopen
= pfnopen
;
160 PFDI_INT(rv
)->pfnread
= pfnread
;
161 PFDI_INT(rv
)->pfnwrite
= pfnwrite
;
162 PFDI_INT(rv
)->pfnclose
= pfnclose
;
163 PFDI_INT(rv
)->pfnseek
= pfnseek
;
164 /* no-brainer: we ignore the cpu type; this is only used
165 for the 16-bit versions in Windows anyhow... */
166 PFDI_INT(rv
)->perf
= perf
;
171 /*******************************************************************
172 * FDI_getoffset (internal)
174 * returns the file pointer position of a cab
176 long FDI_getoffset(HFDI hfdi
, INT_PTR hf
)
178 return PFDI_SEEK(hfdi
, hf
, 0L, SEEK_CUR
);
181 /**********************************************************************
182 * FDI_realloc (internal)
184 * we can't use _msize; the user might not be using malloc, so we require
185 * an explicit specification of the previous size. utterly inefficient.
187 void *FDI_realloc(HFDI hfdi
, void *mem
, size_t prevsize
, size_t newsize
)
191 size_t copysize
= (prevsize
< newsize
) ? prevsize
: newsize
;
192 if (prevsize
== newsize
) return mem
;
193 rslt
= PFDI_ALLOC(hfdi
, newsize
);
195 for (irslt
= (char *)rslt
, imem
= (char *)mem
; (copysize
); copysize
--)
197 PFDI_FREE(hfdi
, mem
);
201 /**********************************************************************
202 * FDI_read_string (internal)
204 * allocate and read an aribitrarily long string from the cabinet
206 char *FDI_read_string(HFDI hfdi
, INT_PTR hf
, long cabsize
)
210 base
= FDI_getoffset(hfdi
, hf
),
211 maxlen
= cabsize
- base
;
214 cab_UBYTE
*buf
= NULL
;
216 TRACE("(hfdi == ^%p, hf == %d)\n", hfdi
, hf
);
219 if (len
> maxlen
) len
= maxlen
;
220 if (!(buf
= FDI_realloc(hfdi
, buf
, oldlen
, len
))) break;
222 if (!PFDI_READ(hfdi
, hf
, buf
, len
)) break;
224 /* search for a null terminator in what we've just read */
225 for (i
=0; i
< len
; i
++) {
226 if (!buf
[i
]) {ok
=TRUE
; break;}
231 ERR("WARNING: cabinet is truncated\n");
235 PFDI_SEEK(hfdi
, hf
, base
, SEEK_SET
);
241 PFDI_FREE(hfdi
, buf
);
243 ERR("out of memory!\n");
247 /* otherwise, set the stream to just after the string and return */
248 PFDI_SEEK(hfdi
, hf
, base
+ ((cab_off_t
) strlen((char *) buf
)) + 1, SEEK_SET
);
253 /******************************************************************
254 * FDI_read_entries (internal)
256 * process the cabinet header in the style of FDIIsCabinet, but
257 * without the sanity checks (and bug)
259 * if pmii is non-null, some info not expressed in FDICABINETINFO struct
260 * will be stored there... responsibility to free the enclosed stuff is
261 * delegated to the caller in this case.
263 BOOL
FDI_read_entries(
266 PFDICABINETINFO pfdici
,
267 PMORE_ISCAB_INFO pmii
)
269 int num_folders
, num_files
, header_resv
, folder_resv
= 0;
270 LONG base_offset
, cabsize
;
271 USHORT setid
, cabidx
, flags
;
272 cab_UBYTE buf
[64], block_resv
;
273 char *prevname
= NULL
, *previnfo
= NULL
, *nextname
= NULL
, *nextinfo
= NULL
;
275 TRACE("(hfdi == ^%p, hf == %d, pfdici == ^%p)\n", hfdi
, hf
, pfdici
);
277 if (pmii
) ZeroMemory(pmii
, sizeof(MORE_ISCAB_INFO
));
279 /* get basic offset & size info */
280 base_offset
= FDI_getoffset(hfdi
, hf
);
282 if (PFDI_SEEK(hfdi
, hf
, 0, SEEK_END
) == -1) {
283 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_NOT_A_CABINET
;
284 PFDI_INT(hfdi
)->perf
->erfType
= 0;
285 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
289 cabsize
= FDI_getoffset(hfdi
, hf
);
291 if ((cabsize
== -1) || (base_offset
== -1) ||
292 ( PFDI_SEEK(hfdi
, hf
, base_offset
, SEEK_SET
) == -1 )) {
293 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_NOT_A_CABINET
;
294 PFDI_INT(hfdi
)->perf
->erfType
= 0;
295 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
299 /* read in the CFHEADER */
300 if (PFDI_READ(hfdi
, hf
, buf
, cfhead_SIZEOF
) != cfhead_SIZEOF
) {
301 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_NOT_A_CABINET
;
302 PFDI_INT(hfdi
)->perf
->erfType
= 0;
303 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
307 /* check basic MSCF signature */
308 if (EndGetI32(buf
+cfhead_Signature
) != 0x4643534d) {
309 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_NOT_A_CABINET
;
310 PFDI_INT(hfdi
)->perf
->erfType
= 0;
311 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
315 /* get the number of folders */
316 num_folders
= EndGetI16(buf
+cfhead_NumFolders
);
317 if (num_folders
== 0) {
318 /* PONDERME: is this really invalid? */
319 WARN("weird cabinet detect failure: no folders in cabinet\n");
320 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_NOT_A_CABINET
;
321 PFDI_INT(hfdi
)->perf
->erfType
= 0;
322 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
326 /* get the number of files */
327 num_files
= EndGetI16(buf
+cfhead_NumFiles
);
328 if (num_files
== 0) {
329 /* PONDERME: is this really invalid? */
330 WARN("weird cabinet detect failure: no files in cabinet\n");
331 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_NOT_A_CABINET
;
332 PFDI_INT(hfdi
)->perf
->erfType
= 0;
333 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
338 setid
= EndGetI16(buf
+cfhead_SetID
);
340 /* cabinet (set) index */
341 cabidx
= EndGetI16(buf
+cfhead_CabinetIndex
);
343 /* check the header revision */
344 if ((buf
[cfhead_MajorVersion
] > 1) ||
345 (buf
[cfhead_MajorVersion
] == 1 && buf
[cfhead_MinorVersion
] > 3))
347 WARN("cabinet format version > 1.3\n");
348 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_UNKNOWN_CABINET_VERSION
;
349 PFDI_INT(hfdi
)->perf
->erfType
= 0; /* ? */
350 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
354 /* pull the flags out */
355 flags
= EndGetI16(buf
+cfhead_Flags
);
357 /* read the reserved-sizes part of header, if present */
358 if (flags
& cfheadRESERVE_PRESENT
) {
359 if (PFDI_READ(hfdi
, hf
, buf
, cfheadext_SIZEOF
) != cfheadext_SIZEOF
) {
360 ERR("bunk reserve-sizes?\n");
361 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
362 PFDI_INT(hfdi
)->perf
->erfType
= 0; /* ? */
363 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
367 header_resv
= EndGetI16(buf
+cfheadext_HeaderReserved
);
368 if (pmii
) pmii
->header_resv
= header_resv
;
369 folder_resv
= buf
[cfheadext_FolderReserved
];
370 if (pmii
) pmii
->folder_resv
= folder_resv
;
371 block_resv
= buf
[cfheadext_DataReserved
];
372 if (pmii
) pmii
->block_resv
= block_resv
;
374 if (header_resv
> 60000) {
375 WARN("WARNING; header reserved space > 60000\n");
378 /* skip the reserved header */
379 if ((header_resv
) && (PFDI_SEEK(hfdi
, hf
, header_resv
, SEEK_CUR
) == -1)) {
380 ERR("seek failure: header_resv\n");
381 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
382 PFDI_INT(hfdi
)->perf
->erfType
= 0; /* ? */
383 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
388 if (flags
& cfheadPREV_CABINET
) {
389 prevname
= FDI_read_string(hfdi
, hf
, cabsize
);
391 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
392 PFDI_INT(hfdi
)->perf
->erfType
= 0; /* ? */
393 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
397 pmii
->prevname
= prevname
;
399 PFDI_FREE(hfdi
, prevname
);
400 previnfo
= FDI_read_string(hfdi
, hf
, cabsize
);
403 pmii
->previnfo
= previnfo
;
405 PFDI_FREE(hfdi
, previnfo
);
409 if (flags
& cfheadNEXT_CABINET
) {
410 nextname
= FDI_read_string(hfdi
, hf
, cabsize
);
412 if ((flags
& cfheadPREV_CABINET
) && pmii
) {
413 if (pmii
->prevname
) PFDI_FREE(hfdi
, prevname
);
414 if (pmii
->previnfo
) PFDI_FREE(hfdi
, previnfo
);
416 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
417 PFDI_INT(hfdi
)->perf
->erfType
= 0; /* ? */
418 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
422 pmii
->nextname
= nextname
;
424 PFDI_FREE(hfdi
, nextname
);
425 nextinfo
= FDI_read_string(hfdi
, hf
, cabsize
);
428 pmii
->nextinfo
= nextinfo
;
430 PFDI_FREE(hfdi
, nextinfo
);
434 /* we could process the whole cabinet searching for problems;
435 instead lets stop here. Now let's fill out the paperwork */
436 pfdici
->cbCabinet
= cabsize
;
437 pfdici
->cFolders
= num_folders
;
438 pfdici
->cFiles
= num_files
;
439 pfdici
->setID
= setid
;
440 pfdici
->iCabinet
= cabidx
;
441 pfdici
->fReserve
= (flags
& cfheadRESERVE_PRESENT
) ? TRUE
: FALSE
;
442 pfdici
->hasprev
= (flags
& cfheadPREV_CABINET
) ? TRUE
: FALSE
;
443 pfdici
->hasnext
= (flags
& cfheadNEXT_CABINET
) ? TRUE
: FALSE
;
447 /***********************************************************************
448 * FDIIsCabinet (CABINET.21)
450 BOOL __cdecl
FDIIsCabinet(
453 PFDICABINETINFO pfdici
)
457 TRACE("(hfdi == ^%p, hf == ^%d, pfdici == ^%p)\n", hfdi
, hf
, pfdici
);
459 if (!REALLY_IS_FDI(hfdi
)) {
460 ERR("REALLY_IS_FDI failed on ^%p\n", hfdi
);
461 SetLastError(ERROR_INVALID_HANDLE
);
467 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CABINET_NOT_FOUND
;
468 PFDI_INT(hfdi
)->perf
->erfType
= ERROR_INVALID_HANDLE
;
469 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
470 SetLastError(ERROR_INVALID_HANDLE
);
476 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_NONE
;
477 PFDI_INT(hfdi
)->perf
->erfType
= ERROR_BAD_ARGUMENTS
;
478 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
479 SetLastError(ERROR_BAD_ARGUMENTS
);
482 rv
= FDI_read_entries(hfdi
, hf
, pfdici
, NULL
);
485 pfdici
->hasnext
= FALSE
; /* yuck. duplicate apparent cabinet.dll bug */
490 /* FIXME: eliminate global variables */
491 static cab_UBYTE q_length_base
[27], q_length_extra
[27], q_extra_bits
[42];
492 static cab_ULONG q_position_base
[42];
494 /******************************************************************
495 * QTMfdi_initmodel (internal)
497 * Initialise a model which decodes symbols from [s] to [s]+[n]-1
499 void QTMfdi_initmodel(struct QTMmodel
*m
, struct QTMmodelsym
*sym
, int n
, int s
) {
504 memset(m
->tabloc
, 0xFF, sizeof(m
->tabloc
)); /* clear out look-up table */
505 for (i
= 0; i
< n
; i
++) {
506 m
->tabloc
[i
+s
] = i
; /* set up a look-up entry for symbol */
507 m
->syms
[i
].sym
= i
+s
; /* actual symbol */
508 m
->syms
[i
].cumfreq
= n
-i
; /* current frequency of that symbol */
510 m
->syms
[n
].cumfreq
= 0;
513 /******************************************************************
514 * QTMfdi_init (internal)
516 int QTMfdi_init(int window
, int level
, fdi_decomp_state
*decomp_state
) {
517 int wndsize
= 1 << window
, msz
= window
* 2, i
;
520 /* QTM supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
521 /* if a previously allocated window is big enough, keep it */
522 if (window
< 10 || window
> 21) return DECR_DATAFORMAT
;
523 if (QTM(actual_size
) < wndsize
) {
524 if (QTM(window
)) PFDI_FREE(CAB(hfdi
), QTM(window
));
528 if (!(QTM(window
) = PFDI_ALLOC(CAB(hfdi
), wndsize
))) return DECR_NOMEMORY
;
529 QTM(actual_size
) = wndsize
;
531 QTM(window_size
) = wndsize
;
532 QTM(window_posn
) = 0;
534 /* initialise static slot/extrabits tables */
535 for (i
= 0, j
= 0; i
< 27; i
++) {
536 q_length_extra
[i
] = (i
== 26) ? 0 : (i
< 2 ? 0 : i
- 2) >> 2;
537 q_length_base
[i
] = j
; j
+= 1 << ((i
== 26) ? 5 : q_length_extra
[i
]);
539 for (i
= 0, j
= 0; i
< 42; i
++) {
540 q_extra_bits
[i
] = (i
< 2 ? 0 : i
-2) >> 1;
541 q_position_base
[i
] = j
; j
+= 1 << q_extra_bits
[i
];
544 /* initialise arithmetic coding models */
546 QTMfdi_initmodel(&QTM(model7
), &QTM(m7sym
)[0], 7, 0);
548 QTMfdi_initmodel(&QTM(model00
), &QTM(m00sym
)[0], 0x40, 0x00);
549 QTMfdi_initmodel(&QTM(model40
), &QTM(m40sym
)[0], 0x40, 0x40);
550 QTMfdi_initmodel(&QTM(model80
), &QTM(m80sym
)[0], 0x40, 0x80);
551 QTMfdi_initmodel(&QTM(modelC0
), &QTM(mC0sym
)[0], 0x40, 0xC0);
553 /* model 4 depends on table size, ranges from 20 to 24 */
554 QTMfdi_initmodel(&QTM(model4
), &QTM(m4sym
)[0], (msz
< 24) ? msz
: 24, 0);
555 /* model 5 depends on table size, ranges from 20 to 36 */
556 QTMfdi_initmodel(&QTM(model5
), &QTM(m5sym
)[0], (msz
< 36) ? msz
: 36, 0);
557 /* model 6pos depends on table size, ranges from 20 to 42 */
558 QTMfdi_initmodel(&QTM(model6pos
), &QTM(m6psym
)[0], msz
, 0);
559 QTMfdi_initmodel(&QTM(model6len
), &QTM(m6lsym
)[0], 27, 0);
564 /* FIXME: Eliminate global variables */
565 static cab_ULONG lzx_position_base
[51];
566 static cab_UBYTE extra_bits
[51];
568 /************************************************************
569 * LZXfdi_init (internal)
571 int LZXfdi_init(int window
, fdi_decomp_state
*decomp_state
) {
572 cab_ULONG wndsize
= 1 << window
;
573 int i
, j
, posn_slots
;
575 /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
576 /* if a previously allocated window is big enough, keep it */
577 if (window
< 15 || window
> 21) return DECR_DATAFORMAT
;
578 if (LZX(actual_size
) < wndsize
) {
579 if (LZX(window
)) PFDI_FREE(CAB(hfdi
), LZX(window
));
583 if (!(LZX(window
) = PFDI_ALLOC(CAB(hfdi
), wndsize
))) return DECR_NOMEMORY
;
584 LZX(actual_size
) = wndsize
;
586 LZX(window_size
) = wndsize
;
588 /* initialise static tables */
589 for (i
=0, j
=0; i
<= 50; i
+= 2) {
590 extra_bits
[i
] = extra_bits
[i
+1] = j
; /* 0,0,0,0,1,1,2,2,3,3... */
591 if ((i
!= 0) && (j
< 17)) j
++; /* 0,0,1,2,3,4...15,16,17,17,17,17... */
593 for (i
=0, j
=0; i
<= 50; i
++) {
594 lzx_position_base
[i
] = j
; /* 0,1,2,3,4,6,8,12,16,24,32,... */
595 j
+= 1 << extra_bits
[i
]; /* 1,1,1,1,2,2,4,4,8,8,16,16,32,32,... */
598 /* calculate required position slots */
599 if (window
== 20) posn_slots
= 42;
600 else if (window
== 21) posn_slots
= 50;
601 else posn_slots
= window
<< 1;
603 /*posn_slots=i=0; while (i < wndsize) i += 1 << extra_bits[posn_slots++]; */
605 LZX(R0
) = LZX(R1
) = LZX(R2
) = 1;
606 LZX(main_elements
) = LZX_NUM_CHARS
+ (posn_slots
<< 3);
607 LZX(header_read
) = 0;
608 LZX(frames_read
) = 0;
609 LZX(block_remaining
) = 0;
610 LZX(block_type
) = LZX_BLOCKTYPE_INVALID
;
611 LZX(intel_curpos
) = 0;
612 LZX(intel_started
) = 0;
613 LZX(window_posn
) = 0;
615 /* initialise tables to 0 (because deltas will be applied to them) */
616 for (i
= 0; i
< LZX_MAINTREE_MAXSYMBOLS
; i
++) LZX(MAINTREE_len
)[i
] = 0;
617 for (i
= 0; i
< LZX_LENGTH_MAXSYMBOLS
; i
++) LZX(LENGTH_len
)[i
] = 0;
622 /****************************************************
623 * NONEfdi_decomp(internal)
625 int NONEfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
627 if (inlen
!= outlen
) return DECR_ILLEGALDATA
;
628 memcpy(CAB(outbuf
), CAB(inbuf
), (size_t) inlen
);
632 /********************************************************
633 * Ziphuft_free (internal)
635 void fdi_Ziphuft_free(HFDI hfdi
, struct Ziphuft
*t
)
637 register struct Ziphuft
*p
, *q
;
639 /* Go through linked list, freeing from the allocated (t[-1]) address. */
641 while (p
!= (struct Ziphuft
*)NULL
)
649 /*********************************************************
650 * fdi_Ziphuft_build (internal)
652 cab_LONG
fdi_Ziphuft_build(cab_ULONG
*b
, cab_ULONG n
, cab_ULONG s
, cab_UWORD
*d
, cab_UWORD
*e
,
653 struct Ziphuft
**t
, cab_LONG
*m
, fdi_decomp_state
*decomp_state
)
655 cab_ULONG a
; /* counter for codes of length k */
656 cab_ULONG el
; /* length of EOB code (value 256) */
657 cab_ULONG f
; /* i repeats in table every f entries */
658 cab_LONG g
; /* maximum code length */
659 cab_LONG h
; /* table level */
660 register cab_ULONG i
; /* counter, current code */
661 register cab_ULONG j
; /* counter */
662 register cab_LONG k
; /* number of bits in current code */
663 cab_LONG
*l
; /* stack of bits per table */
664 register cab_ULONG
*p
; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */
665 register struct Ziphuft
*q
; /* points to current table */
666 struct Ziphuft r
; /* table entry for structure assignment */
667 register cab_LONG w
; /* bits before this table == (l * h) */
668 cab_ULONG
*xp
; /* pointer into x */
669 cab_LONG y
; /* number of dummy codes added */
670 cab_ULONG z
; /* number of entries in current table */
674 /* Generate counts for each bit length */
675 el
= n
> 256 ? b
[256] : ZIPBMAX
; /* set length of EOB code, if any */
677 for(i
= 0; i
< ZIPBMAX
+1; ++i
)
682 ZIP(c
)[*p
]++; p
++; /* assume all entries <= ZIPBMAX */
684 if (ZIP(c
)[0] == n
) /* null input--all zero length codes */
686 *t
= (struct Ziphuft
*)NULL
;
691 /* Find minimum and maximum length, bound *m by those */
692 for (j
= 1; j
<= ZIPBMAX
; j
++)
695 k
= j
; /* minimum code length */
696 if ((cab_ULONG
)*m
< j
)
698 for (i
= ZIPBMAX
; i
; i
--)
701 g
= i
; /* maximum code length */
702 if ((cab_ULONG
)*m
> i
)
705 /* Adjust last length count to fill out codes, if needed */
706 for (y
= 1 << j
; j
< i
; j
++, y
<<= 1)
707 if ((y
-= ZIP(c
)[j
]) < 0)
708 return 2; /* bad input: more codes than bits */
709 if ((y
-= ZIP(c
)[i
]) < 0)
713 /* Generate starting offsets LONGo the value table for each length */
715 p
= ZIP(c
) + 1; xp
= ZIP(x
) + 2;
717 { /* note that i == g from above */
721 /* Make a table of values in order of bit lengths */
725 ZIP(v
)[ZIP(x
)[j
]++] = i
;
729 /* Generate the Huffman codes and for each, make the table entries */
730 ZIP(x
)[0] = i
= 0; /* first Huffman code is zero */
731 p
= ZIP(v
); /* grab values in bit order */
732 h
= -1; /* no tables yet--level -1 */
733 w
= l
[-1] = 0; /* no bits decoded yet */
734 ZIP(u
)[0] = (struct Ziphuft
*)NULL
; /* just to keep compilers happy */
735 q
= (struct Ziphuft
*)NULL
; /* ditto */
738 /* go through the bit lengths (k already is bits in shortest code) */
744 /* here i is the Huffman code of length k bits for value *p */
745 /* make tables up to required level */
748 w
+= l
[h
++]; /* add bits already decoded */
750 /* compute minimum size table less than or equal to *m bits */
751 z
= (z
= g
- w
) > (cab_ULONG
)*m
? *m
: z
; /* upper limit */
752 if ((f
= 1 << (j
= k
- w
)) > a
+ 1) /* try a k-w bit table */
753 { /* too few codes for k-w bit table */
754 f
-= a
+ 1; /* deduct codes from patterns left */
756 while (++j
< z
) /* try smaller tables up to z bits */
758 if ((f
<<= 1) <= *++xp
)
759 break; /* enough codes to use up j bits */
760 f
-= *xp
; /* else deduct codes from patterns */
763 if ((cab_ULONG
)w
+ j
> el
&& (cab_ULONG
)w
< el
)
764 j
= el
- w
; /* make EOB code end at table */
765 z
= 1 << j
; /* table entries for j-bit table */
766 l
[h
] = j
; /* set table size in stack */
768 /* allocate and link in new table */
769 if (!(q
= (struct Ziphuft
*) PFDI_ALLOC(CAB(hfdi
), (z
+ 1)*sizeof(struct Ziphuft
))))
772 fdi_Ziphuft_free(CAB(hfdi
), ZIP(u
)[0]);
773 return 3; /* not enough memory */
775 *t
= q
+ 1; /* link to list for Ziphuft_free() */
776 *(t
= &(q
->v
.t
)) = (struct Ziphuft
*)NULL
;
777 ZIP(u
)[h
] = ++q
; /* table starts after link */
779 /* connect to last table, if there is one */
782 ZIP(x
)[h
] = i
; /* save pattern for backing up */
783 r
.b
= (cab_UBYTE
)l
[h
-1]; /* bits to dump before this table */
784 r
.e
= (cab_UBYTE
)(16 + j
); /* bits in this table */
785 r
.v
.t
= q
; /* pointer to this table */
786 j
= (i
& ((1 << w
) - 1)) >> (w
- l
[h
-1]);
787 ZIP(u
)[h
-1][j
] = r
; /* connect to last table */
791 /* set up table entry in r */
792 r
.b
= (cab_UBYTE
)(k
- w
);
794 r
.e
= 99; /* out of values--invalid code */
797 r
.e
= (cab_UBYTE
)(*p
< 256 ? 16 : 15); /* 256 is end-of-block code */
798 r
.v
.n
= *p
++; /* simple code is just the value */
802 r
.e
= (cab_UBYTE
)e
[*p
- s
]; /* non-simple--look up in lists */
806 /* fill code-like entries with r */
808 for (j
= i
>> w
; j
< z
; j
+= f
)
811 /* backwards increment the k-bit code i */
812 for (j
= 1 << (k
- 1); i
& j
; j
>>= 1)
816 /* backup over finished tables */
817 while ((i
& ((1 << w
) - 1)) != ZIP(x
)[h
])
818 w
-= l
[--h
]; /* don't need to update q */
822 /* return actual size of base table */
825 /* Return true (1) if we were given an incomplete table */
826 return y
!= 0 && g
!= 1;
829 /*********************************************************
830 * fdi_Zipinflate_codes (internal)
832 cab_LONG
fdi_Zipinflate_codes(struct Ziphuft
*tl
, struct Ziphuft
*td
,
833 cab_LONG bl
, cab_LONG bd
, fdi_decomp_state
*decomp_state
)
835 register cab_ULONG e
; /* table entry flag/number of extra bits */
836 cab_ULONG n
, d
; /* length and index for copy */
837 cab_ULONG w
; /* current window position */
838 struct Ziphuft
*t
; /* pointer to table entry */
839 cab_ULONG ml
, md
; /* masks for bl and bd bits */
840 register cab_ULONG b
; /* bit buffer */
841 register cab_ULONG k
; /* number of bits in bit buffer */
843 /* make local copies of globals */
844 b
= ZIP(bb
); /* initialize bit buffer */
846 w
= ZIP(window_posn
); /* initialize window position */
848 /* inflate the coded data */
849 ml
= Zipmask
[bl
]; /* precompute masks for speed */
854 ZIPNEEDBITS((cab_ULONG
)bl
)
855 if((e
= (t
= tl
+ ((cab_ULONG
)b
& ml
))->e
) > 16)
863 } while ((e
= (t
= t
->v
.t
+ ((cab_ULONG
)b
& Zipmask
[e
]))->e
) > 16);
865 if (e
== 16) /* then it's a literal */
866 CAB(outbuf
)[w
++] = (cab_UBYTE
)t
->v
.n
;
867 else /* it's an EOB or a length */
869 /* exit if end of block */
873 /* get length of block to copy */
875 n
= t
->v
.n
+ ((cab_ULONG
)b
& Zipmask
[e
]);
878 /* decode distance of block to copy */
879 ZIPNEEDBITS((cab_ULONG
)bd
)
880 if ((e
= (t
= td
+ ((cab_ULONG
)b
& md
))->e
) > 16)
887 } while ((e
= (t
= t
->v
.t
+ ((cab_ULONG
)b
& Zipmask
[e
]))->e
) > 16);
890 d
= w
- t
->v
.n
- ((cab_ULONG
)b
& Zipmask
[e
]);
894 n
-= (e
= (e
= ZIPWSIZE
- ((d
&= ZIPWSIZE
-1) > w
? d
: w
)) > n
?n
:e
);
897 CAB(outbuf
)[w
++] = CAB(outbuf
)[d
++];
903 /* restore the globals from the locals */
904 ZIP(window_posn
) = w
; /* restore global window pointer */
905 ZIP(bb
) = b
; /* restore global bit buffer */
912 /***********************************************************
913 * Zipinflate_stored (internal)
915 cab_LONG
fdi_Zipinflate_stored(fdi_decomp_state
*decomp_state
)
916 /* "decompress" an inflated type 0 (stored) block. */
918 cab_ULONG n
; /* number of bytes in block */
919 cab_ULONG w
; /* current window position */
920 register cab_ULONG b
; /* bit buffer */
921 register cab_ULONG k
; /* number of bits in bit buffer */
923 /* make local copies of globals */
924 b
= ZIP(bb
); /* initialize bit buffer */
926 w
= ZIP(window_posn
); /* initialize window position */
928 /* go to byte boundary */
932 /* get the length and its complement */
934 n
= ((cab_ULONG
)b
& 0xffff);
937 if (n
!= (cab_ULONG
)((~b
) & 0xffff))
938 return 1; /* error in compressed data */
941 /* read and output the compressed data */
945 CAB(outbuf
)[w
++] = (cab_UBYTE
)b
;
949 /* restore the globals from the locals */
950 ZIP(window_posn
) = w
; /* restore global window pointer */
951 ZIP(bb
) = b
; /* restore global bit buffer */
956 /******************************************************
957 * fdi_Zipinflate_fixed (internal)
959 cab_LONG
fdi_Zipinflate_fixed(fdi_decomp_state
*decomp_state
)
961 struct Ziphuft
*fixed_tl
;
962 struct Ziphuft
*fixed_td
;
963 cab_LONG fixed_bl
, fixed_bd
;
964 cab_LONG i
; /* temporary variable */
970 for(i
= 0; i
< 144; i
++)
976 for(; i
< 288; i
++) /* make a complete, but wrong code set */
979 if((i
= fdi_Ziphuft_build(l
, 288, 257, (cab_UWORD
*) Zipcplens
,
980 (cab_UWORD
*) Zipcplext
, &fixed_tl
, &fixed_bl
, decomp_state
)))
984 for(i
= 0; i
< 30; i
++) /* make an incomplete code set */
987 if((i
= fdi_Ziphuft_build(l
, 30, 0, (cab_UWORD
*) Zipcpdist
, (cab_UWORD
*) Zipcpdext
,
988 &fixed_td
, &fixed_bd
, decomp_state
)) > 1)
990 fdi_Ziphuft_free(CAB(hfdi
), fixed_tl
);
994 /* decompress until an end-of-block code */
995 i
= fdi_Zipinflate_codes(fixed_tl
, fixed_td
, fixed_bl
, fixed_bd
, decomp_state
);
997 fdi_Ziphuft_free(CAB(hfdi
), fixed_td
);
998 fdi_Ziphuft_free(CAB(hfdi
), fixed_tl
);
1002 /**************************************************************
1003 * fdi_Zipinflate_dynamic (internal)
1005 cab_LONG
fdi_Zipinflate_dynamic(fdi_decomp_state
*decomp_state
)
1006 /* decompress an inflated type 2 (dynamic Huffman codes) block. */
1008 cab_LONG i
; /* temporary variables */
1011 cab_ULONG l
; /* last length */
1012 cab_ULONG m
; /* mask for bit lengths table */
1013 cab_ULONG n
; /* number of lengths to get */
1014 struct Ziphuft
*tl
; /* literal/length code table */
1015 struct Ziphuft
*td
; /* distance code table */
1016 cab_LONG bl
; /* lookup bits for tl */
1017 cab_LONG bd
; /* lookup bits for td */
1018 cab_ULONG nb
; /* number of bit length codes */
1019 cab_ULONG nl
; /* number of literal/length codes */
1020 cab_ULONG nd
; /* number of distance codes */
1021 register cab_ULONG b
; /* bit buffer */
1022 register cab_ULONG k
; /* number of bits in bit buffer */
1024 /* make local bit buffer */
1029 /* read in table lengths */
1031 nl
= 257 + ((cab_ULONG
)b
& 0x1f); /* number of literal/length codes */
1034 nd
= 1 + ((cab_ULONG
)b
& 0x1f); /* number of distance codes */
1037 nb
= 4 + ((cab_ULONG
)b
& 0xf); /* number of bit length codes */
1039 if(nl
> 288 || nd
> 32)
1040 return 1; /* bad lengths */
1042 /* read in bit-length-code lengths */
1043 for(j
= 0; j
< nb
; j
++)
1046 ll
[Zipborder
[j
]] = (cab_ULONG
)b
& 7;
1050 ll
[Zipborder
[j
]] = 0;
1052 /* build decoding table for trees--single level, 7 bit lookup */
1054 if((i
= fdi_Ziphuft_build(ll
, 19, 19, NULL
, NULL
, &tl
, &bl
, decomp_state
)) != 0)
1057 fdi_Ziphuft_free(CAB(hfdi
), tl
);
1058 return i
; /* incomplete code set */
1061 /* read in literal and distance code lengths */
1065 while((cab_ULONG
)i
< n
)
1067 ZIPNEEDBITS((cab_ULONG
)bl
)
1068 j
= (td
= tl
+ ((cab_ULONG
)b
& m
))->b
;
1071 if (j
< 16) /* length of code in bits (0..15) */
1072 ll
[i
++] = l
= j
; /* save last length in l */
1073 else if (j
== 16) /* repeat last length 3 to 6 times */
1076 j
= 3 + ((cab_ULONG
)b
& 3);
1078 if((cab_ULONG
)i
+ j
> n
)
1083 else if (j
== 17) /* 3 to 10 zero length codes */
1086 j
= 3 + ((cab_ULONG
)b
& 7);
1088 if ((cab_ULONG
)i
+ j
> n
)
1094 else /* j == 18: 11 to 138 zero length codes */
1097 j
= 11 + ((cab_ULONG
)b
& 0x7f);
1099 if ((cab_ULONG
)i
+ j
> n
)
1107 /* free decoding table for trees */
1108 fdi_Ziphuft_free(CAB(hfdi
), tl
);
1110 /* restore the global bit buffer */
1114 /* build the decoding tables for literal/length and distance codes */
1116 if((i
= fdi_Ziphuft_build(ll
, nl
, 257, (cab_UWORD
*) Zipcplens
, (cab_UWORD
*) Zipcplext
,
1117 &tl
, &bl
, decomp_state
)) != 0)
1120 fdi_Ziphuft_free(CAB(hfdi
), tl
);
1121 return i
; /* incomplete code set */
1124 fdi_Ziphuft_build(ll
+ nl
, nd
, 0, (cab_UWORD
*) Zipcpdist
, (cab_UWORD
*) Zipcpdext
,
1125 &td
, &bd
, decomp_state
);
1127 /* decompress until an end-of-block code */
1128 if(fdi_Zipinflate_codes(tl
, td
, bl
, bd
, decomp_state
))
1131 /* free the decoding tables, return */
1132 fdi_Ziphuft_free(CAB(hfdi
), tl
);
1133 fdi_Ziphuft_free(CAB(hfdi
), td
);
1137 /*****************************************************
1138 * fdi_Zipinflate_block (internal)
1140 cab_LONG
fdi_Zipinflate_block(cab_LONG
*e
, fdi_decomp_state
*decomp_state
) /* e == last block flag */
1141 { /* decompress an inflated block */
1142 cab_ULONG t
; /* block type */
1143 register cab_ULONG b
; /* bit buffer */
1144 register cab_ULONG k
; /* number of bits in bit buffer */
1146 /* make local bit buffer */
1150 /* read in last block bit */
1152 *e
= (cab_LONG
)b
& 1;
1155 /* read in block type */
1157 t
= (cab_ULONG
)b
& 3;
1160 /* restore the global bit buffer */
1164 /* inflate that block type */
1166 return fdi_Zipinflate_dynamic(decomp_state
);
1168 return fdi_Zipinflate_stored(decomp_state
);
1170 return fdi_Zipinflate_fixed(decomp_state
);
1171 /* bad block type */
1175 /****************************************************
1176 * ZIPfdi_decomp(internal)
1178 int ZIPfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
1180 cab_LONG e
; /* last block flag */
1182 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1184 ZIP(inpos
) = CAB(inbuf
);
1185 ZIP(bb
) = ZIP(bk
) = ZIP(window_posn
) = 0;
1186 if(outlen
> ZIPWSIZE
)
1187 return DECR_DATAFORMAT
;
1189 /* CK = Chris Kirmse, official Microsoft purloiner */
1190 if(ZIP(inpos
)[0] != 0x43 || ZIP(inpos
)[1] != 0x4B)
1191 return DECR_ILLEGALDATA
;
1195 if(fdi_Zipinflate_block(&e
, decomp_state
))
1196 return DECR_ILLEGALDATA
;
1199 /* return success */
1203 /*******************************************************************
1204 * QTMfdi_decomp(internal)
1206 int QTMfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
)
1208 cab_UBYTE
*inpos
= CAB(inbuf
);
1209 cab_UBYTE
*window
= QTM(window
);
1210 cab_UBYTE
*runsrc
, *rundest
;
1212 cab_ULONG window_posn
= QTM(window_posn
);
1213 cab_ULONG window_size
= QTM(window_size
);
1215 /* used by bitstream macros */
1216 register int bitsleft
, bitrun
, bitsneed
;
1217 register cab_ULONG bitbuf
;
1219 /* used by GET_SYMBOL */
1224 int extra
, togo
= outlen
, match_length
= 0, copy_length
;
1225 cab_UBYTE selector
, sym
;
1226 cab_ULONG match_offset
= 0;
1228 cab_UWORD H
= 0xFFFF, L
= 0, C
;
1230 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1232 /* read initial value of C */
1236 /* apply 2^x-1 mask */
1237 window_posn
&= window_size
- 1;
1238 /* runs can't straddle the window wraparound */
1239 if ((window_posn
+ togo
) > window_size
) {
1240 TRACE("straddled run\n");
1241 return DECR_DATAFORMAT
;
1245 GET_SYMBOL(model7
, selector
);
1248 GET_SYMBOL(model00
, sym
); window
[window_posn
++] = sym
; togo
--;
1251 GET_SYMBOL(model40
, sym
); window
[window_posn
++] = sym
; togo
--;
1254 GET_SYMBOL(model80
, sym
); window
[window_posn
++] = sym
; togo
--;
1257 GET_SYMBOL(modelC0
, sym
); window
[window_posn
++] = sym
; togo
--;
1261 /* selector 4 = fixed length of 3 */
1262 GET_SYMBOL(model4
, sym
);
1263 Q_READ_BITS(extra
, q_extra_bits
[sym
]);
1264 match_offset
= q_position_base
[sym
] + extra
+ 1;
1269 /* selector 5 = fixed length of 4 */
1270 GET_SYMBOL(model5
, sym
);
1271 Q_READ_BITS(extra
, q_extra_bits
[sym
]);
1272 match_offset
= q_position_base
[sym
] + extra
+ 1;
1277 /* selector 6 = variable length */
1278 GET_SYMBOL(model6len
, sym
);
1279 Q_READ_BITS(extra
, q_length_extra
[sym
]);
1280 match_length
= q_length_base
[sym
] + extra
+ 5;
1281 GET_SYMBOL(model6pos
, sym
);
1282 Q_READ_BITS(extra
, q_extra_bits
[sym
]);
1283 match_offset
= q_position_base
[sym
] + extra
+ 1;
1287 TRACE("Selector is bogus\n");
1288 return DECR_ILLEGALDATA
;
1291 /* if this is a match */
1292 if (selector
>= 4) {
1293 rundest
= window
+ window_posn
;
1294 togo
-= match_length
;
1296 /* copy any wrapped around source data */
1297 if (window_posn
>= match_offset
) {
1299 runsrc
= rundest
- match_offset
;
1301 runsrc
= rundest
+ (window_size
- match_offset
);
1302 copy_length
= match_offset
- window_posn
;
1303 if (copy_length
< match_length
) {
1304 match_length
-= copy_length
;
1305 window_posn
+= copy_length
;
1306 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1310 window_posn
+= match_length
;
1312 /* copy match data - no worries about destination wraps */
1313 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1315 } /* while (togo > 0) */
1318 TRACE("Frame overflow, this_run = %d\n", togo
);
1319 return DECR_ILLEGALDATA
;
1322 memcpy(CAB(outbuf
), window
+ ((!window_posn
) ? window_size
: window_posn
) -
1325 QTM(window_posn
) = window_posn
;
1329 /************************************************************
1330 * fdi_lzx_read_lens (internal)
1332 int fdi_lzx_read_lens(cab_UBYTE
*lens
, cab_ULONG first
, cab_ULONG last
, struct lzx_bits
*lb
,
1333 fdi_decomp_state
*decomp_state
) {
1337 register cab_ULONG bitbuf
= lb
->bb
;
1338 register int bitsleft
= lb
->bl
;
1339 cab_UBYTE
*inpos
= lb
->ip
;
1342 for (x
= 0; x
< 20; x
++) {
1344 LENTABLE(PRETREE
)[x
] = y
;
1346 BUILD_TABLE(PRETREE
);
1348 for (x
= first
; x
< last
; ) {
1349 READ_HUFFSYM(PRETREE
, z
);
1351 READ_BITS(y
, 4); y
+= 4;
1352 while (y
--) lens
[x
++] = 0;
1355 READ_BITS(y
, 5); y
+= 20;
1356 while (y
--) lens
[x
++] = 0;
1359 READ_BITS(y
, 1); y
+= 4;
1360 READ_HUFFSYM(PRETREE
, z
);
1361 z
= lens
[x
] - z
; if (z
< 0) z
+= 17;
1362 while (y
--) lens
[x
++] = z
;
1365 z
= lens
[x
] - z
; if (z
< 0) z
+= 17;
1376 /*******************************************************
1377 * LZXfdi_decomp(internal)
1379 int LZXfdi_decomp(int inlen
, int outlen
, fdi_decomp_state
*decomp_state
) {
1380 cab_UBYTE
*inpos
= CAB(inbuf
);
1381 cab_UBYTE
*endinp
= inpos
+ inlen
;
1382 cab_UBYTE
*window
= LZX(window
);
1383 cab_UBYTE
*runsrc
, *rundest
;
1384 cab_UWORD
*hufftbl
; /* used in READ_HUFFSYM macro as chosen decoding table */
1386 cab_ULONG window_posn
= LZX(window_posn
);
1387 cab_ULONG window_size
= LZX(window_size
);
1388 cab_ULONG R0
= LZX(R0
);
1389 cab_ULONG R1
= LZX(R1
);
1390 cab_ULONG R2
= LZX(R2
);
1392 register cab_ULONG bitbuf
;
1393 register int bitsleft
;
1394 cab_ULONG match_offset
, i
,j
,k
; /* ijk used in READ_HUFFSYM macro */
1395 struct lzx_bits lb
; /* used in READ_LENGTHS macro */
1397 int togo
= outlen
, this_run
, main_element
, aligned_bits
;
1398 int match_length
, copy_length
, length_footer
, extra
, verbatim_bits
;
1400 TRACE("(inlen == %d, outlen == %d)\n", inlen
, outlen
);
1404 /* read header if necessary */
1405 if (!LZX(header_read
)) {
1407 READ_BITS(k
, 1); if (k
) { READ_BITS(i
,16); READ_BITS(j
,16); }
1408 LZX(intel_filesize
) = (i
<< 16) | j
; /* or 0 if not encoded */
1409 LZX(header_read
) = 1;
1412 /* main decoding loop */
1414 /* last block finished, new block expected */
1415 if (LZX(block_remaining
) == 0) {
1416 if (LZX(block_type
) == LZX_BLOCKTYPE_UNCOMPRESSED
) {
1417 if (LZX(block_length
) & 1) inpos
++; /* realign bitstream to word */
1421 READ_BITS(LZX(block_type
), 3);
1424 LZX(block_remaining
) = LZX(block_length
) = (i
<< 8) | j
;
1426 switch (LZX(block_type
)) {
1427 case LZX_BLOCKTYPE_ALIGNED
:
1428 for (i
= 0; i
< 8; i
++) { READ_BITS(j
, 3); LENTABLE(ALIGNED
)[i
] = j
; }
1429 BUILD_TABLE(ALIGNED
);
1430 /* rest of aligned header is same as verbatim */
1432 case LZX_BLOCKTYPE_VERBATIM
:
1433 READ_LENGTHS(MAINTREE
, 0, 256, fdi_lzx_read_lens
);
1434 READ_LENGTHS(MAINTREE
, 256, LZX(main_elements
), fdi_lzx_read_lens
);
1435 BUILD_TABLE(MAINTREE
);
1436 if (LENTABLE(MAINTREE
)[0xE8] != 0) LZX(intel_started
) = 1;
1438 READ_LENGTHS(LENGTH
, 0, LZX_NUM_SECONDARY_LENGTHS
, fdi_lzx_read_lens
);
1439 BUILD_TABLE(LENGTH
);
1442 case LZX_BLOCKTYPE_UNCOMPRESSED
:
1443 LZX(intel_started
) = 1; /* because we can't assume otherwise */
1444 ENSURE_BITS(16); /* get up to 16 pad bits into the buffer */
1445 if (bitsleft
> 16) inpos
-= 2; /* and align the bitstream! */
1446 R0
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1447 R1
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1448 R2
= inpos
[0]|(inpos
[1]<<8)|(inpos
[2]<<16)|(inpos
[3]<<24);inpos
+=4;
1452 return DECR_ILLEGALDATA
;
1456 /* buffer exhaustion check */
1457 if (inpos
> endinp
) {
1458 /* it's possible to have a file where the next run is less than
1459 * 16 bits in size. In this case, the READ_HUFFSYM() macro used
1460 * in building the tables will exhaust the buffer, so we should
1461 * allow for this, but not allow those accidentally read bits to
1462 * be used (so we check that there are at least 16 bits
1463 * remaining - in this boundary case they aren't really part of
1464 * the compressed data)
1466 if (inpos
> (endinp
+2) || bitsleft
< 16) return DECR_ILLEGALDATA
;
1469 while ((this_run
= LZX(block_remaining
)) > 0 && togo
> 0) {
1470 if (this_run
> togo
) this_run
= togo
;
1472 LZX(block_remaining
) -= this_run
;
1474 /* apply 2^x-1 mask */
1475 window_posn
&= window_size
- 1;
1476 /* runs can't straddle the window wraparound */
1477 if ((window_posn
+ this_run
) > window_size
)
1478 return DECR_DATAFORMAT
;
1480 switch (LZX(block_type
)) {
1482 case LZX_BLOCKTYPE_VERBATIM
:
1483 while (this_run
> 0) {
1484 READ_HUFFSYM(MAINTREE
, main_element
);
1486 if (main_element
< LZX_NUM_CHARS
) {
1487 /* literal: 0 to LZX_NUM_CHARS-1 */
1488 window
[window_posn
++] = main_element
;
1492 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1493 main_element
-= LZX_NUM_CHARS
;
1495 match_length
= main_element
& LZX_NUM_PRIMARY_LENGTHS
;
1496 if (match_length
== LZX_NUM_PRIMARY_LENGTHS
) {
1497 READ_HUFFSYM(LENGTH
, length_footer
);
1498 match_length
+= length_footer
;
1500 match_length
+= LZX_MIN_MATCH
;
1502 match_offset
= main_element
>> 3;
1504 if (match_offset
> 2) {
1505 /* not repeated offset */
1506 if (match_offset
!= 3) {
1507 extra
= extra_bits
[match_offset
];
1508 READ_BITS(verbatim_bits
, extra
);
1509 match_offset
= lzx_position_base
[match_offset
]
1510 - 2 + verbatim_bits
;
1516 /* update repeated offset LRU queue */
1517 R2
= R1
; R1
= R0
; R0
= match_offset
;
1519 else if (match_offset
== 0) {
1522 else if (match_offset
== 1) {
1524 R1
= R0
; R0
= match_offset
;
1526 else /* match_offset == 2 */ {
1528 R2
= R0
; R0
= match_offset
;
1531 rundest
= window
+ window_posn
;
1532 this_run
-= match_length
;
1534 /* copy any wrapped around source data */
1535 if (window_posn
>= match_offset
) {
1537 runsrc
= rundest
- match_offset
;
1539 runsrc
= rundest
+ (window_size
- match_offset
);
1540 copy_length
= match_offset
- window_posn
;
1541 if (copy_length
< match_length
) {
1542 match_length
-= copy_length
;
1543 window_posn
+= copy_length
;
1544 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1548 window_posn
+= match_length
;
1550 /* copy match data - no worries about destination wraps */
1551 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1556 case LZX_BLOCKTYPE_ALIGNED
:
1557 while (this_run
> 0) {
1558 READ_HUFFSYM(MAINTREE
, main_element
);
1560 if (main_element
< LZX_NUM_CHARS
) {
1561 /* literal: 0 to LZX_NUM_CHARS-1 */
1562 window
[window_posn
++] = main_element
;
1566 /* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
1567 main_element
-= LZX_NUM_CHARS
;
1569 match_length
= main_element
& LZX_NUM_PRIMARY_LENGTHS
;
1570 if (match_length
== LZX_NUM_PRIMARY_LENGTHS
) {
1571 READ_HUFFSYM(LENGTH
, length_footer
);
1572 match_length
+= length_footer
;
1574 match_length
+= LZX_MIN_MATCH
;
1576 match_offset
= main_element
>> 3;
1578 if (match_offset
> 2) {
1579 /* not repeated offset */
1580 extra
= extra_bits
[match_offset
];
1581 match_offset
= lzx_position_base
[match_offset
] - 2;
1583 /* verbatim and aligned bits */
1585 READ_BITS(verbatim_bits
, extra
);
1586 match_offset
+= (verbatim_bits
<< 3);
1587 READ_HUFFSYM(ALIGNED
, aligned_bits
);
1588 match_offset
+= aligned_bits
;
1590 else if (extra
== 3) {
1591 /* aligned bits only */
1592 READ_HUFFSYM(ALIGNED
, aligned_bits
);
1593 match_offset
+= aligned_bits
;
1595 else if (extra
> 0) { /* extra==1, extra==2 */
1596 /* verbatim bits only */
1597 READ_BITS(verbatim_bits
, extra
);
1598 match_offset
+= verbatim_bits
;
1600 else /* extra == 0 */ {
1605 /* update repeated offset LRU queue */
1606 R2
= R1
; R1
= R0
; R0
= match_offset
;
1608 else if (match_offset
== 0) {
1611 else if (match_offset
== 1) {
1613 R1
= R0
; R0
= match_offset
;
1615 else /* match_offset == 2 */ {
1617 R2
= R0
; R0
= match_offset
;
1620 rundest
= window
+ window_posn
;
1621 this_run
-= match_length
;
1623 /* copy any wrapped around source data */
1624 if (window_posn
>= match_offset
) {
1626 runsrc
= rundest
- match_offset
;
1628 runsrc
= rundest
+ (window_size
- match_offset
);
1629 copy_length
= match_offset
- window_posn
;
1630 if (copy_length
< match_length
) {
1631 match_length
-= copy_length
;
1632 window_posn
+= copy_length
;
1633 while (copy_length
-- > 0) *rundest
++ = *runsrc
++;
1637 window_posn
+= match_length
;
1639 /* copy match data - no worries about destination wraps */
1640 while (match_length
-- > 0) *rundest
++ = *runsrc
++;
1645 case LZX_BLOCKTYPE_UNCOMPRESSED
:
1646 if ((inpos
+ this_run
) > endinp
) return DECR_ILLEGALDATA
;
1647 memcpy(window
+ window_posn
, inpos
, (size_t) this_run
);
1648 inpos
+= this_run
; window_posn
+= this_run
;
1652 return DECR_ILLEGALDATA
; /* might as well */
1658 if (togo
!= 0) return DECR_ILLEGALDATA
;
1659 memcpy(CAB(outbuf
), window
+ ((!window_posn
) ? window_size
: window_posn
) -
1660 outlen
, (size_t) outlen
);
1662 LZX(window_posn
) = window_posn
;
1667 /* intel E8 decoding */
1668 if ((LZX(frames_read
)++ < 32768) && LZX(intel_filesize
) != 0) {
1669 if (outlen
<= 6 || !LZX(intel_started
)) {
1670 LZX(intel_curpos
) += outlen
;
1673 cab_UBYTE
*data
= CAB(outbuf
);
1674 cab_UBYTE
*dataend
= data
+ outlen
- 10;
1675 cab_LONG curpos
= LZX(intel_curpos
);
1676 cab_LONG filesize
= LZX(intel_filesize
);
1677 cab_LONG abs_off
, rel_off
;
1679 LZX(intel_curpos
) = curpos
+ outlen
;
1681 while (data
< dataend
) {
1682 if (*data
++ != 0xE8) { curpos
++; continue; }
1683 abs_off
= data
[0] | (data
[1]<<8) | (data
[2]<<16) | (data
[3]<<24);
1684 if ((abs_off
>= -curpos
) && (abs_off
< filesize
)) {
1685 rel_off
= (abs_off
>= 0) ? abs_off
- curpos
: abs_off
+ filesize
;
1686 data
[0] = (cab_UBYTE
) rel_off
;
1687 data
[1] = (cab_UBYTE
) (rel_off
>> 8);
1688 data
[2] = (cab_UBYTE
) (rel_off
>> 16);
1689 data
[3] = (cab_UBYTE
) (rel_off
>> 24);
1699 /**********************************************************
1700 * fdi_decomp (internal)
1702 int fdi_decomp(struct fdi_file
*fi
, int savemode
, fdi_decomp_state
*decomp_state
)
1704 cab_ULONG bytes
= savemode
? fi
->length
: fi
->offset
- CAB(offset
);
1705 cab_UBYTE buf
[cfdata_SIZEOF
], *data
;
1706 cab_UWORD inlen
, len
, outlen
, cando
;
1710 TRACE("(fi == ^%p, savemode == %d)\n", fi
, savemode
);
1713 /* cando = the max number of bytes we can do */
1714 cando
= CAB(outlen
);
1715 if (cando
> bytes
) cando
= bytes
;
1718 if (cando
&& savemode
)
1719 PFDI_WRITE(CAB(hfdi
), CAB(filehf
), CAB(outpos
), cando
);
1721 CAB(outpos
) += cando
;
1722 CAB(outlen
) -= cando
;
1723 bytes
-= cando
; if (!bytes
) break;
1725 /* we only get here if we emptied the output buffer */
1727 /* read data header + data */
1729 while (outlen
== 0) {
1730 /* read the block header, skip the reserved part */
1731 if (PFDI_READ(CAB(hfdi
), CAB(cabhf
), buf
, cfdata_SIZEOF
) != cfdata_SIZEOF
)
1734 if (PFDI_SEEK(CAB(hfdi
), CAB(cabhf
), CAB(block_resv
), SEEK_CUR
) == -1)
1737 /* we shouldn't get blocks over CAB_INPUTMAX in size */
1738 data
= CAB(inbuf
) + inlen
;
1739 len
= EndGetI16(buf
+cfdata_CompressedSize
);
1741 if (inlen
> CAB_INPUTMAX
) return DECR_INPUT
;
1742 if (PFDI_READ(CAB(hfdi
), CAB(cabhf
), data
, len
) != len
)
1745 /* clear two bytes after read-in data */
1746 data
[len
+1] = data
[len
+2] = 0;
1748 /* perform checksum test on the block (if one is stored) */
1749 cksum
= EndGetI32(buf
+cfdata_CheckSum
);
1750 if (cksum
&& cksum
!= checksum(buf
+4, 4, checksum(data
, len
, 0)))
1751 return DECR_CHECKSUM
; /* checksum is wrong */
1753 /* outlen=0 means this block was part of a split block */
1754 outlen
= EndGetI16(buf
+cfdata_UncompressedSize
);
1758 cab = CAB(current)->cab[++CAB(split)];
1759 if (!cabinet_open(cab)) return DECR_INPUT;
1760 cabinet_seek(cab, CAB(current)->offset[CAB(split)]); */
1761 FIXME("split block... ack! fix this.\n");
1766 /* decompress block */
1767 if ((err
= CAB(decompress
)(inlen
, outlen
, decomp_state
)))
1769 CAB(outlen
) = outlen
;
1770 CAB(outpos
) = CAB(outbuf
);
1776 /***********************************************************************
1777 * FDICopy (CABINET.22)
1779 BOOL __cdecl
FDICopy(
1784 PFNFDINOTIFY pfnfdin
,
1785 PFNFDIDECRYPT pfnfdid
,
1788 FDICABINETINFO fdici
;
1789 FDINOTIFICATION fdin
;
1790 MORE_ISCAB_INFO mii
;
1793 char fullpath
[MAX_PATH
];
1794 size_t pathlen
, filenamelen
;
1795 char emptystring
= '\0';
1797 BOOL initialcab
= TRUE
;
1798 struct fdi_folder
*fol
= NULL
, *linkfol
= NULL
;
1799 struct fdi_file
*file
= NULL
, *linkfile
= NULL
;
1800 fdi_decomp_state _decomp_state
;
1801 fdi_decomp_state
*decomp_state
= &_decomp_state
;
1803 TRACE("(hfdi == ^%p, pszCabinet == ^%p, pszCabPath == ^%p, flags == %0d, \
1804 pfnfdin == ^%p, pfnfdid == ^%p, pvUser == ^%p)\n",
1805 hfdi
, pszCabinet
, pszCabPath
, flags
, pfnfdin
, pfnfdid
, pvUser
);
1807 if (!REALLY_IS_FDI(hfdi
)) {
1808 SetLastError(ERROR_INVALID_HANDLE
);
1812 ZeroMemory(decomp_state
, sizeof(fdi_decomp_state
));
1814 pathlen
= (pszCabPath
) ? strlen(pszCabPath
) : 0;
1815 filenamelen
= (pszCabinet
) ? strlen(pszCabinet
) : 0;
1817 /* slight overestimation here to save CPU cycles in the developer's brain */
1818 if ((pathlen
+ filenamelen
+ 3) > MAX_PATH
) {
1819 ERR("MAX_PATH exceeded.\n");
1820 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CABINET_NOT_FOUND
;
1821 PFDI_INT(hfdi
)->perf
->erfType
= ERROR_FILE_NOT_FOUND
;
1822 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
1823 SetLastError(ERROR_FILE_NOT_FOUND
);
1827 /* paste the path and filename together */
1830 for (i
= 0; i
< pathlen
; i
++) fullpath
[idx
++] = pszCabPath
[i
];
1831 if (fullpath
[idx
- 1] != '\\') fullpath
[idx
++] = '\\';
1833 if (filenamelen
) for (i
= 0; i
< filenamelen
; i
++) fullpath
[idx
++] = pszCabinet
[i
];
1834 fullpath
[idx
] = '\0';
1836 TRACE("full cab path/file name: %s\n", debugstr_a(fullpath
));
1838 /* get a handle to the cabfile */
1839 cabhf
= PFDI_OPEN(hfdi
, fullpath
, _O_BINARY
| _O_RDONLY
| _O_SEQUENTIAL
, 0);
1841 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CABINET_NOT_FOUND
;
1842 PFDI_INT(hfdi
)->perf
->erfType
= ERROR_FILE_NOT_FOUND
;
1843 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
1844 SetLastError(ERROR_FILE_NOT_FOUND
);
1848 /* check if it's really a cabfile. Note that this doesn't implement the bug */
1849 if (!FDI_read_entries(hfdi
, cabhf
, &fdici
, &mii
)) {
1850 ERR("FDIIsCabinet failed.\n");
1851 PFDI_CLOSE(hfdi
, cabhf
);
1855 /* cabinet notification */
1856 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
1857 fdin
.setID
= fdici
.setID
;
1858 fdin
.iCabinet
= fdici
.iCabinet
;
1860 fdin
.psz1
= (mii
.nextname
) ? mii
.nextname
: &emptystring
;
1861 fdin
.psz2
= (mii
.nextinfo
) ? mii
.nextinfo
: &emptystring
;
1862 fdin
.psz3
= pszCabPath
;
1864 if (((*pfnfdin
)(fdintCABINET_INFO
, &fdin
))) {
1865 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_USER_ABORT
;
1866 PFDI_INT(hfdi
)->perf
->erfType
= 0;
1867 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
1872 for (i
= 0; i
< fdici
.cFolders
; i
++) {
1873 if (PFDI_READ(hfdi
, cabhf
, buf
, cffold_SIZEOF
) != cffold_SIZEOF
) {
1874 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
1875 PFDI_INT(hfdi
)->perf
->erfType
= 0;
1876 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
1880 if (mii
.folder_resv
> 0)
1881 PFDI_SEEK(hfdi
, cabhf
, mii
.folder_resv
, SEEK_CUR
);
1883 fol
= (struct fdi_folder
*) PFDI_ALLOC(hfdi
, sizeof(struct fdi_folder
));
1885 ERR("out of memory!\n");
1886 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_ALLOC_FAIL
;
1887 PFDI_INT(hfdi
)->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1888 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
1889 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1892 ZeroMemory(fol
, sizeof(struct fdi_folder
));
1893 if (!CAB(firstfol
)) CAB(firstfol
) = fol
;
1895 fol
->offset
[0] = (cab_off_t
) EndGetI32(buf
+cffold_DataOffset
);
1896 fol
->num_blocks
= EndGetI16(buf
+cffold_NumBlocks
);
1897 fol
->comp_type
= EndGetI16(buf
+cffold_CompType
);
1900 linkfol
->next
= fol
;
1905 for (i
= 0; i
< fdici
.cFiles
; i
++) {
1906 if (PFDI_READ(hfdi
, cabhf
, buf
, cffile_SIZEOF
) != cffile_SIZEOF
) {
1907 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
1908 PFDI_INT(hfdi
)->perf
->erfType
= 0;
1909 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
1913 file
= (struct fdi_file
*) PFDI_ALLOC(hfdi
, sizeof(struct fdi_file
));
1915 ERR("out of memory!\n");
1916 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_ALLOC_FAIL
;
1917 PFDI_INT(hfdi
)->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
1918 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
1919 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1922 ZeroMemory(file
, sizeof(struct fdi_file
));
1923 if (!CAB(firstfile
)) CAB(firstfile
) = file
;
1925 file
->length
= EndGetI32(buf
+cffile_UncompressedSize
);
1926 file
->offset
= EndGetI32(buf
+cffile_FolderOffset
);
1927 file
->index
= EndGetI16(buf
+cffile_FolderIndex
);
1928 file
->time
= EndGetI16(buf
+cffile_Time
);
1929 file
->date
= EndGetI16(buf
+cffile_Date
);
1930 file
->attribs
= EndGetI16(buf
+cffile_Attribs
);
1931 file
->filename
= FDI_read_string(hfdi
, cabhf
, fdici
.cbCabinet
);
1933 if (!file
->filename
) {
1934 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
1935 PFDI_INT(hfdi
)->perf
->erfType
= 0;
1936 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
1941 linkfile
->next
= file
;
1945 for (file
= CAB(firstfile
); (file
); file
= file
->next
) {
1946 /* partial file notification (do it just once for the first cabinet) */
1947 if (initialcab
&& ((file
->index
& cffileCONTINUED_FROM_PREV
) == cffileCONTINUED_FROM_PREV
)) {
1948 /* OK, more MS bugs to simulate here, I think. I don't have a huge spanning
1949 * cabinet to test this theory on ATM, but here's the deal. The SDK says that we
1950 * are supposed to notify the user of the filename and "disk name" (info) of
1951 * the cabinet where the spanning file /started/. That would certainly be convenient
1952 * for the consumer, who could decide to abort everything and try to start over with
1953 * that cabinet so as not to create a front-truncated output file. Note that this
1954 * task would be a horrible bitch from the implementor's (wine's) perspective: the
1955 * information is associated nowhere with the file header and is not to be found in
1956 * the cabinet header. So we would have to open the previous cabinet, and check
1957 * if it contains a single spanning file that's continued from yet another prior cabinet,
1958 * and so-on, until we find the beginning. Note that cabextract.c has code to do exactly
1959 * this. Luckily, MS clearly didn't implement this logic, so we don't have to either.
1960 * Watching the callbacks (and debugmsg +file) clearly shows that they don't open
1961 * the preceeding cabinet -- and therefore, I deduce, there is NO WAY they could
1962 * have implemented what's in the spec. Instead, they are obviously just returning
1963 * the previous cabinet and it's info from the header of this cabinet. So we shall
1964 * do the same. Of course, I could be missing something...
1966 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
1968 fdin
.psz1
= (char *)file
->filename
;
1969 fdin
.psz2
= (mii
.prevname
) ? mii
.prevname
: &emptystring
;
1970 fdin
.psz3
= (mii
.previnfo
) ? mii
.previnfo
: &emptystring
;
1972 if (((*pfnfdin
)(fdintPARTIAL_FILE
, &fdin
))) {
1973 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_USER_ABORT
;
1974 PFDI_INT(hfdi
)->perf
->erfType
= 0;
1975 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
1978 /* I don't think we are supposed to decompress partial files */
1979 file
->oppressed
= TRUE
;
1981 if (file
->oppressed
) {
1984 /* fdintCOPY_FILE notification (TODO: skip for spanning cab's we already should have hf) */
1985 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
1987 fdin
.psz1
= (char *)file
->filename
;
1988 fdin
.cb
= file
->length
;
1989 fdin
.date
= file
->date
;
1990 fdin
.time
= file
->time
;
1991 fdin
.attribs
= file
->attribs
;
1992 if ((filehf
= ((*pfnfdin
)(fdintCOPY_FILE
, &fdin
))) == -1) {
1993 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_USER_ABORT
;
1994 PFDI_INT(hfdi
)->perf
->erfType
= 0;
1995 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
2001 cab_UWORD comptype
= fol
->comp_type
;
2002 int ct1
= comptype
& cffoldCOMPTYPE_MASK
;
2005 TRACE("Extracting file %s as requested by callee.\n", debugstr_a(file
->filename
));
2007 /* set up decomp_state (unneccesary?); at least
2008 ignore trailing three pointers in the struct */
2009 ZeroMemory(decomp_state
, sizeof(fdi_decomp_state
) - sizeof(void*) * 3);
2011 CAB(filehf
) = filehf
;
2013 CAB(current
) = file
->folder
;
2014 CAB(block_resv
) = mii
.block_resv
;
2016 /* set up the appropriate decompressor */
2018 case cffoldCOMPTYPE_NONE
:
2019 CAB(decompress
) = NONEfdi_decomp
;
2021 case cffoldCOMPTYPE_MSZIP
:
2022 CAB(decompress
) = ZIPfdi_decomp
;
2024 case cffoldCOMPTYPE_QUANTUM
:
2025 CAB(decompress
) = QTMfdi_decomp
;
2026 err
= QTMfdi_init((comptype
>> 8) & 0x1f, (comptype
>> 4) & 0xF, decomp_state
);
2028 case cffoldCOMPTYPE_LZX
:
2029 CAB(decompress
) = LZXfdi_decomp
;
2030 err
= LZXfdi_init((comptype
>> 8) & 0x1f, decomp_state
);
2033 err
= DECR_DATAFORMAT
;
2040 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_ALLOC_FAIL
;
2041 PFDI_INT(hfdi
)->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
2042 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
2043 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2046 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
2047 PFDI_INT(hfdi
)->perf
->erfOper
= 0;
2048 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
2052 PFDI_SEEK(CAB(hfdi
), CAB(cabhf
), fol
->offset
[0], SEEK_SET
);
2057 if (file
->offset
> CAB(offset
)) {
2058 /* decode bytes and send them to /dev/null */
2059 switch ((err
= fdi_decomp(file
, 0, decomp_state
))) {
2063 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_ALLOC_FAIL
;
2064 PFDI_INT(hfdi
)->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
2065 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
2066 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2069 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
2070 PFDI_INT(hfdi
)->perf
->erfOper
= 0;
2071 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
2074 CAB(offset
) = file
->offset
;
2077 /* now do the actual decompression */
2078 err
= fdi_decomp(file
, 1, decomp_state
);
2079 if (err
) CAB(current
) = NULL
; else CAB(offset
) += file
->length
;
2085 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_ALLOC_FAIL
;
2086 PFDI_INT(hfdi
)->perf
->erfType
= ERROR_NOT_ENOUGH_MEMORY
;
2087 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
2088 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2091 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_CORRUPT_CABINET
;
2092 PFDI_INT(hfdi
)->perf
->erfOper
= 0;
2093 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
2097 /* fdintCLOSE_FILE_INFO notification */
2098 ZeroMemory(&fdin
, sizeof(FDINOTIFICATION
));
2100 fdin
.psz1
= (char *)file
->filename
;
2102 fdin
.cb
= (file
->attribs
& cffile_A_EXEC
) ? TRUE
: FALSE
;
2103 fdin
.date
= file
->date
;
2104 fdin
.time
= file
->time
;
2105 fdin
.attribs
= file
->attribs
;
2106 err
= ((*pfnfdin
)(fdintCLOSE_FILE_INFO
, &fdin
));
2107 if (err
== FALSE
|| err
== -1) {
2109 * SDK states that even though they indicated failure,
2110 * we are not supposed to try and close the file, so we
2111 * just treat this like all the others
2113 PFDI_INT(hfdi
)->perf
->erfOper
= FDIERROR_USER_ABORT
;
2114 PFDI_INT(hfdi
)->perf
->erfType
= 0;
2115 PFDI_INT(hfdi
)->perf
->fError
= TRUE
;
2121 while (decomp_state
) {
2122 fdi_decomp_state
*prev_fds
;
2123 while (CAB(firstfol
)) {
2124 fol
= CAB(firstfol
);
2125 CAB(firstfol
) = CAB(firstfol
)->next
;
2126 PFDI_FREE(hfdi
, fol
);
2128 while (CAB(firstfile
)) {
2129 file
= CAB(firstfile
);
2130 CAB(firstfile
) = CAB(firstfile
)->next
;
2131 PFDI_FREE(hfdi
, file
);
2133 prev_fds
= decomp_state
;
2134 decomp_state
= CAB(next
);
2135 if (prev_fds
!= &_decomp_state
)
2136 PFDI_FREE(hfdi
, prev_fds
);
2139 /* free the storage remembered by mii */
2140 if (mii
.nextname
) PFDI_FREE(hfdi
, mii
.nextname
);
2141 if (mii
.nextinfo
) PFDI_FREE(hfdi
, mii
.nextinfo
);
2142 if (mii
.prevname
) PFDI_FREE(hfdi
, mii
.prevname
);
2143 if (mii
.previnfo
) PFDI_FREE(hfdi
, mii
.previnfo
);
2145 PFDI_CLOSE(hfdi
, cabhf
);
2148 bail_and_fail
: /* here we free ram before error returns */
2150 while (decomp_state
) {
2151 fdi_decomp_state
*prev_fds
;
2152 while (CAB(firstfol
)) {
2153 fol
= CAB(firstfol
);
2154 CAB(firstfol
) = CAB(firstfol
)->next
;
2155 PFDI_FREE(hfdi
, fol
);
2157 while (CAB(firstfile
)) {
2158 file
= CAB(firstfile
);
2159 CAB(firstfile
) = CAB(firstfile
)->next
;
2160 PFDI_FREE(hfdi
, file
);
2162 prev_fds
= decomp_state
;
2163 decomp_state
= CAB(next
);
2164 if (prev_fds
!= &_decomp_state
)
2165 PFDI_FREE(hfdi
, prev_fds
);
2168 /* free the storage remembered by mii */
2169 if (mii
.nextname
) PFDI_FREE(hfdi
, mii
.nextname
);
2170 if (mii
.nextinfo
) PFDI_FREE(hfdi
, mii
.nextinfo
);
2171 if (mii
.prevname
) PFDI_FREE(hfdi
, mii
.prevname
);
2172 if (mii
.previnfo
) PFDI_FREE(hfdi
, mii
.previnfo
);
2174 PFDI_CLOSE(hfdi
, cabhf
);
2178 /***********************************************************************
2179 * FDIDestroy (CABINET.23)
2181 BOOL __cdecl
FDIDestroy(HFDI hfdi
)
2183 TRACE("(hfdi == ^%p)\n", hfdi
);
2184 if (REALLY_IS_FDI(hfdi
)) {
2185 PFDI_INT(hfdi
)->FDI_Intmagic
= 0; /* paranoia */
2186 PFDI_FREE(hfdi
, hfdi
); /* confusing, but correct */
2189 SetLastError(ERROR_INVALID_HANDLE
);
2194 /***********************************************************************
2195 * FDITruncateCabinet (CABINET.24)
2197 BOOL __cdecl
FDITruncateCabinet(
2199 char *pszCabinetName
,
2200 USHORT iFolderToDelete
)
2202 FIXME("(hfdi == ^%p, pszCabinetName == %s, iFolderToDelete == %hu): stub\n",
2203 hfdi
, debugstr_a(pszCabinetName
), iFolderToDelete
);
2205 if (!REALLY_IS_FDI(hfdi
)) {
2206 SetLastError(ERROR_INVALID_HANDLE
);
2210 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);