Import Wine-20041201 Added: vendor/wine/dlls/cabinet/current/Makefile.in Added: vendor/wine/dlls/cabinet/current/cabextract.c Added: vendor/wine/dlls/cabinet/current/cabinet.h Added: vendor/wine/dlls/cabinet/current/cabinet.rc Added: vendor/wine/dlls/cabinet/current/cabinet.spec Added: vendor/wine/dlls/cabinet/current/cabinet_main.c Added: vendor/wine/dlls/cabinet/current/fci.c Added: vendor/wine/dlls/cabinet/current/fdi.c _____
Added: vendor/wine/dlls/cabinet/current/Makefile.in --- vendor/wine/dlls/cabinet/current/Makefile.in 2004-12-31 13:33:02 UTC (rev 12422) +++ vendor/wine/dlls/cabinet/current/Makefile.in 2004-12-31 13:36:19 UTC (rev 12423) @@ -0,0 +1,18 @@
+TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = cabinet.dll +IMPORTS = kernel32 + +C_SRCS = \ + cabextract.c \ + cabinet_main.c \ + fci.c \ + fdi.c + +RC_SRCS = cabinet.rc + +@MAKE_DLL_RULES@ + +### Dependencies: _____
Added: vendor/wine/dlls/cabinet/current/cabextract.c --- vendor/wine/dlls/cabinet/current/cabextract.c 2004-12-31 13:33:02 UTC (rev 12422) +++ vendor/wine/dlls/cabinet/current/cabextract.c 2004-12-31 13:36:19 UTC (rev 12423) @@ -0,0 +1,2654 @@
+/* + * cabextract.c + * + * Copyright 2000-2002 Stuart Caie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Principal author: Stuart Caie kyzer@4u.net + * + * Based on specification documents from Microsoft Corporation + * Quantum decompression researched and implemented by Matthew Russoto + * Huffman code adapted from unlzx by Dave Tritscher. + * InfoZip team's INFLATE implementation adapted to MSZIP by Dirk Stoecker. + * Major LZX fixes by Jae Jung. + */ + +#include "config.h" + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" + +#include "cabinet.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(cabinet); + +THOSE_ZIP_CONSTS; + +/* all the file IO is abstracted into these routines: + * cabinet_(open|close|read|seek|skip|getoffset) + * file_(open|close|write) + */ + +/* try to open a cabinet file, returns success */ +BOOL cabinet_open(struct cabinet *cab) +{ + const char *name = cab->filename; + HANDLE fh; + + TRACE("(cab == ^%p)\n", cab); + + if ((fh = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE) { + ERR("Couldn't open %s\n", debugstr_a(name)); + return FALSE; + } + + /* seek to end of file and get the length */ + if ((cab->filelen = SetFilePointer(fh, 0, NULL, FILE_END)) == INVALID_SET_FILE_POINTER) { + if (GetLastError() != NO_ERROR) { + ERR("Seek END failed: %s\n", debugstr_a(name)); + CloseHandle(fh); + return FALSE; + } + } + + /* return to the start of the file */ + if (SetFilePointer(fh, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { + ERR("Seek BEGIN failed: %s\n", debugstr_a(name)); + CloseHandle(fh); + return FALSE; + } + + cab->fh = fh; + return TRUE; +} + +/******************************************************************* + * cabinet_close (internal) + * + * close the file handle in a struct cabinet. + */ +void cabinet_close(struct cabinet *cab) { + TRACE("(cab == ^%p)\n", cab); + if (cab->fh) CloseHandle(cab->fh); + cab->fh = 0; +} + +/******************************************************* + * ensure_filepath2 (internal) + */ +BOOL ensure_filepath2(char *path) { + BOOL ret = TRUE; + int len; + char *new_path; + + new_path = HeapAlloc(GetProcessHeap(), 0, (strlen(path) + 1)); + strcpy(new_path, path); + + while((len = strlen(new_path)) && new_path[len - 1] == '\') + new_path[len - 1] = 0; + + TRACE("About to try to create directory %s\n", debugstr_a(new_path)); + while(!CreateDirectoryA(new_path, NULL)) { + char *slash; + DWORD last_error = GetLastError(); + + if(last_error == ERROR_ALREADY_EXISTS) + break; + + if(last_error != ERROR_PATH_NOT_FOUND) { + ret = FALSE; + break; + } + + if(!(slash = strrchr(new_path, '\'))) { + ret = FALSE; + break; + } + + len = slash - new_path; + new_path[len] = 0; + if(! ensure_filepath2(new_path)) { + ret = FALSE; + break; + } + new_path[len] = '\'; + TRACE("New path in next iteration: %s\n", debugstr_a(new_path)); + } + + HeapFree(GetProcessHeap(), 0, new_path); + return ret; +} + + +/********************************************************************** + * ensure_filepath (internal) + * + * ensure_filepath("a\b\c\d.txt") ensures a, a\b and a\b\c exist as dirs + */ +BOOL ensure_filepath(char *path) { + char new_path[MAX_PATH]; + int len, i, lastslashpos = -1; + + TRACE("(path == %s)\n", debugstr_a(path)); + + strcpy(new_path, path); + /* remove trailing slashes (shouldn't need to but wth...) */ + while ((len = strlen(new_path)) && new_path[len - 1] == '\') + new_path[len - 1] = 0; + /* find the position of the last '\' */ + for (i=0; i<MAX_PATH; i++) { + if (new_path[i] == 0) break; + if (new_path[i] == '\') + lastslashpos = i; + } + if (lastslashpos > 0) { + new_path[lastslashpos] = 0; + /* may be trailing slashes but ensure_filepath2 will chop them */ + return ensure_filepath2(new_path); + } else + return TRUE; /* ? */ +} + +/******************************************************************* + * file_open (internal) + * + * opens a file for output, returns success + */ +BOOL file_open(struct cab_file *fi, BOOL lower, LPCSTR dir) +{ + char c, *d, *name; + BOOL ok = FALSE; + const char *s; + + TRACE("(fi == ^%p, lower == %s, dir == %s)\n", fi, lower ? "TRUE" : "FALSE", debugstr_a(dir)); + + if (!(name = malloc(strlen(fi->filename) + (dir ? strlen(dir) : 0) + 2))) { + ERR("out of memory!\n"); + return FALSE; + } + + /* start with blank name */ + *name = 0; + + /* add output directory if needed */ + if (dir) { + strcpy(name, dir); + strcat(name, "\"); + } + + /* remove leading slashes */ + s = (char *) fi->filename; + while (*s == '\') s++; + + /* copy from fi->filename to new name. + * lowercases characters if needed. + */ + d = &name[strlen(name)]; + do { + c = *s++; + *d++ = (lower ? tolower((unsigned char) c) : c); + } while (c); + + /* create directories if needed, attempt to write file */ + if (ensure_filepath(name)) { + fi->fh = CreateFileA(name, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if (fi->fh != INVALID_HANDLE_VALUE) + ok = TRUE; + else { + ERR("CreateFileA returned INVALID_HANDLE_VALUE\n"); + fi->fh = 0; + } + } else + ERR("Couldn't ensure filepath for %s\n", debugstr_a(name)); + + if (!ok) { + ERR("Couldn't open file %s for writing\n", debugstr_a(name)); + } + + /* as full filename is no longer needed, free it */ + free(name); + + return ok; +} + +/******************************************************** + * close_file (internal) + * + * closes a completed file + */ +void file_close(struct cab_file *fi) +{ + TRACE("(fi == ^%p)\n", fi); + + if (fi->fh) { + CloseHandle(fi->fh); + } + fi->fh = 0; +} + +/****************************************************************** + * file_write (internal) + * + * writes from buf to a file specified as a cab_file struct. + * returns success/failure + */ +BOOL file_write(struct cab_file *fi, cab_UBYTE *buf, cab_off_t length) +{ + DWORD bytes_written; + + TRACE("(fi == ^%p, buf == ^%p, length == %u)\n", fi, buf, length); + + if ((!WriteFile( fi->fh, (LPCVOID) buf, length, &bytes_written, FALSE) || + (bytes_written != length))) { + ERR("Error writing file: %s\n", debugstr_a(fi->filename)); + return FALSE; + } + return TRUE; +} + + +/******************************************************************* + * cabinet_skip (internal) + * + * advance the file pointer associated with the cab structure + * by distance bytes + */ +void cabinet_skip(struct cabinet *cab, cab_off_t distance) +{ + TRACE("(cab == ^%p, distance == %u)\n", cab, distance); + if (SetFilePointer(cab->fh, distance, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER) { + if (distance != INVALID_SET_FILE_POINTER) + ERR("%s\n", debugstr_a(cab->filename)); + } +} + +/******************************************************************* + * cabinet_seek (internal) + * + * seek to the specified absolute offset in a cab + */ +void cabinet_seek(struct cabinet *cab, cab_off_t offset) { + TRACE("(cab == ^%p, offset == %u)\n", cab, offset); + if (SetFilePointer(cab->fh, offset, NULL, FILE_BEGIN) != offset) + ERR("%s seek failure\n", debugstr_a(cab->filename)); +} + +/******************************************************************* + * cabinet_getoffset (internal) + * + * returns the file pointer position of a cab + */ +cab_off_t cabinet_getoffset(struct cabinet *cab) +{ + return SetFilePointer(cab->fh, 0, NULL, FILE_CURRENT); +} + +/******************************************************************* + * cabinet_read (internal) + * + * read data from a cabinet, returns success + */ +BOOL cabinet_read(struct cabinet *cab, cab_UBYTE *buf, cab_off_t length) +{ + DWORD bytes_read; + cab_off_t avail = cab->filelen - cabinet_getoffset(cab); + + TRACE("(cab == ^%p, buf == ^%p, length == %u)\n", cab, buf, length); + + if (length > avail) { + WARN("%s: WARNING; cabinet is truncated\n", debugstr_a(cab->filename)); + length = avail; + } + + if (! ReadFile( cab->fh, (LPVOID) buf, length, &bytes_read, NULL )) { + ERR("%s read error\n", debugstr_a(cab->filename)); + return FALSE; + } else if (bytes_read != length) { + ERR("%s read size mismatch\n", debugstr_a(cab->filename)); + return FALSE; + } + + return TRUE; +} + +/********************************************************************** + * cabinet_read_string (internal) + * + * allocate and read an aribitrarily long string from the cabinet + */ +char *cabinet_read_string(struct cabinet *cab) +{ + cab_off_t len=256, base = cabinet_getoffset(cab), maxlen = cab->filelen - base; + BOOL ok = FALSE; + unsigned int i; + cab_UBYTE *buf = NULL; + + TRACE("(cab == ^%p)\n", cab); + + do { + if (len > maxlen) len = maxlen; + if (!(buf = realloc(buf, (size_t) len))) break; + if (!cabinet_read(cab, buf, (size_t) len)) break; + + /* search for a null terminator in what we've just read */ + for (i=0; i < len; i++) { + if (!buf[i]) {ok=TRUE; break;} + } + + if (!ok) { + if (len == maxlen) { + ERR("%s: WARNING; cabinet is truncated\n", debugstr_a(cab->filename)); + break; + } + len += 256; + cabinet_seek(cab, base); + } + } while (!ok); + + if (!ok) { + if (buf) + free(buf); + else + ERR("out of memory!\n"); + return NULL; + } + + /* otherwise, set the stream to just after the string and return */ + cabinet_seek(cab, base + ((cab_off_t) strlen((char *) buf)) + 1); + + return (char *) buf; +} + +/****************************************************************** + * cabinet_read_entries (internal) + * + * reads the header and all folder and file entries in this cabinet + */ +BOOL cabinet_read_entries(struct cabinet *cab) +{ + int num_folders, num_files, header_resv, folder_resv = 0, i; + struct cab_folder *fol, *linkfol = NULL; + struct cab_file *file, *linkfile = NULL; + cab_off_t base_offset; + cab_UBYTE buf[64]; + + TRACE("(cab == ^%p)\n", cab); + + /* read in the CFHEADER */ + base_offset = cabinet_getoffset(cab); + if (!cabinet_read(cab, buf, cfhead_SIZEOF)) { + return FALSE; + } + + /* check basic MSCF signature */ + if (EndGetI32(buf+cfhead_Signature) != 0x4643534d) { + ERR("%s: not a Microsoft cabinet file\n", debugstr_a(cab->filename)); + return FALSE; + } + + /* get the number of folders */ + num_folders = EndGetI16(buf+cfhead_NumFolders); + if (num_folders == 0) { + ERR("%s: no folders in cabinet\n", debugstr_a(cab->filename)); + return FALSE; + } + + /* get the number of files */ + num_files = EndGetI16(buf+cfhead_NumFiles); + if (num_files == 0) { + ERR("%s: no files in cabinet\n", debugstr_a(cab->filename)); + return FALSE; + } + + /* just check the header revision */ + if ((buf[cfhead_MajorVersion] > 1) || + (buf[cfhead_MajorVersion] == 1 && buf[cfhead_MinorVersion] > 3)) + { + WARN("%s: WARNING; cabinet format version > 1.3\n", debugstr_a(cab->filename)); + } + + /* read the reserved-sizes part of header, if present */ + cab->flags = EndGetI16(buf+cfhead_Flags); + if (cab->flags & cfheadRESERVE_PRESENT) { + if (!cabinet_read(cab, buf, cfheadext_SIZEOF)) return FALSE; + header_resv = EndGetI16(buf+cfheadext_HeaderReserved); + folder_resv = buf[cfheadext_FolderReserved]; + cab->block_resv = buf[cfheadext_DataReserved]; + + if (header_resv > 60000) { + WARN("%s: WARNING; header reserved space > 60000\n", debugstr_a(cab->filename)); + } + + /* skip the reserved header */ + if (header_resv) + if (SetFilePointer(cab->fh, (cab_off_t) header_resv, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER) + ERR("seek failure: %s\n", debugstr_a(cab->filename)); + } + + if (cab->flags & cfheadPREV_CABINET) { + cab->prevname = cabinet_read_string(cab); + if (!cab->prevname) return FALSE; + cab->previnfo = cabinet_read_string(cab); + } + + if (cab->flags & cfheadNEXT_CABINET) { + cab->nextname = cabinet_read_string(cab); + if (!cab->nextname) return FALSE; + cab->nextinfo = cabinet_read_string(cab); + } + + /* read folders */ + for (i = 0; i < num_folders; i++) { + if (!cabinet_read(cab, buf, cffold_SIZEOF)) return FALSE; + if (folder_resv) cabinet_skip(cab, folder_resv); + + fol = (struct cab_folder *) calloc(1, sizeof(struct cab_folder)); + if (!fol) { + ERR("out of memory!\n"); + return FALSE; + } + + fol->cab[0] = cab; + fol->offset[0] = base_offset + (cab_off_t) EndGetI32(buf+cffold_DataOffset); + fol->num_blocks = EndGetI16(buf+cffold_NumBlocks); + fol->comp_type = EndGetI16(buf+cffold_CompType); + + if (!linkfol) + cab->folders = fol; + else + linkfol->next = fol; + + linkfol = fol; + } + + /* read files */ + for (i = 0; i < num_files; i++) { + if (!cabinet_read(cab, buf, cffile_SIZEOF)) + return FALSE; + + file = (struct cab_file *) calloc(1, sizeof(struct cab_file)); + if (!file) { + ERR("out of memory!\n"); + return FALSE; + } + + file->length = EndGetI32(buf+cffile_UncompressedSize); + file->offset = EndGetI32(buf+cffile_FolderOffset); + file->index = EndGetI16(buf+cffile_FolderIndex); + file->time = EndGetI16(buf+cffile_Time); + file->date = EndGetI16(buf+cffile_Date); + file->attribs = EndGetI16(buf+cffile_Attribs); + file->filename = cabinet_read_string(cab); + + if (!file->filename) { + free(file); + return FALSE; + } + + if (!linkfile) + cab->files = file; + else + linkfile->next = file; + + linkfile = file; + } + return TRUE; +} + +/*********************************************************** + * load_cab_offset (internal) + * + * validates and reads file entries from a cabinet at offset [offset] in + * file [name]. Returns a cabinet structure if successful, or NULL + * otherwise. + */ +struct cabinet *load_cab_offset(LPCSTR name, cab_off_t offset) +{ + struct cabinet *cab = (struct cabinet *) calloc(1, sizeof(struct cabinet)); + int ok; + + TRACE("(name == %s, offset == %u)\n", debugstr_a(name), offset); + + if (!cab) return NULL; + + cab->filename = name; + if ((ok = cabinet_open(cab))) { + cabinet_seek(cab, offset); + ok = cabinet_read_entries(cab); + cabinet_close(cab); + } + + if (ok) return cab; + free(cab); + return NULL; +} + +/* MSZIP decruncher */ + +/* Dirk Stoecker wrote the ZIP decoder, based on the InfoZip deflate code */ + +/******************************************************** + * Ziphuft_free (internal) + */ +void Ziphuft_free(struct Ziphuft *t) +{ + register struct Ziphuft *p, *q; + + /* Go through linked list, freeing from the allocated (t[-1]) address. */ + p = t; + while (p != (struct Ziphuft *)NULL) + { + q = (--p)->v.t; + free(p); + p = q; + } +} + +/********************************************************* + * Ziphuft_build (internal) + */ +cab_LONG Ziphuft_build(cab_ULONG *b, cab_ULONG n, cab_ULONG s, cab_UWORD *d, cab_UWORD *e, +struct Ziphuft **t, cab_LONG *m, cab_decomp_state *decomp_state) +{ + cab_ULONG a; /* counter for codes of length k */ + cab_ULONG el; /* length of EOB code (value 256) */ + cab_ULONG f; /* i repeats in table every f entries */ + cab_LONG g; /* maximum code length */ + cab_LONG h; /* table level */ + register cab_ULONG i; /* counter, current code */ + register cab_ULONG j; /* counter */ + register cab_LONG k; /* number of bits in current code */ + cab_LONG *l; /* stack of bits per table */ + register cab_ULONG *p; /* pointer into ZIP(c)[],ZIP(b)[],ZIP(v)[] */ + register struct Ziphuft *q; /* points to current table */ + struct Ziphuft r; /* table entry for structure assignment */ + register cab_LONG w; /* bits before this table == (l * h) */ + cab_ULONG *xp; /* pointer into x */ + cab_LONG y; /* number of dummy codes added */ + cab_ULONG z; /* number of entries in current table */ + + l = ZIP(lx)+1; + + /* Generate counts for each bit length */ + el = n > 256 ? b[256] : ZIPBMAX; /* set length of EOB code, if any */ + + for(i = 0; i < ZIPBMAX+1; ++i) + ZIP(c)[i] = 0; + p = b; i = n; + do + { + ZIP(c)[*p]++; p++; /* assume all entries <= ZIPBMAX */ + } while (--i); + if (ZIP(c)[0] == n) /* null input--all zero length codes */ + { + *t = (struct Ziphuft *)NULL; + *m = 0; + return 0; + } + + /* Find minimum and maximum length, bound *m by those */ + for (j = 1; j <= ZIPBMAX; j++) + if (ZIP(c)[j]) + break; + k = j; /* minimum code length */ + if ((cab_ULONG)*m < j) + *m = j; + for (i = ZIPBMAX; i; i--) + if (ZIP(c)[i]) + break; + g = i; /* maximum code length */ + if ((cab_ULONG)*m > i) + *m = i; + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= ZIP(c)[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= ZIP(c)[i]) < 0) + return 2; + ZIP(c)[i] += y; + + /* Generate starting offsets LONGo the value table for each length */ + ZIP(x)[1] = j = 0; + p = ZIP(c) + 1; xp = ZIP(x) + 2; + while (--i) + { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do{ + if ((j = *p++) != 0) + ZIP(v)[ZIP(x)[j]++] = i; + } while (++i < n); + + + /* Generate the Huffman codes and for each, make the table entries */ + ZIP(x)[0] = i = 0; /* first Huffman code is zero */ + p = ZIP(v); /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = l[-1] = 0; /* no bits decoded yet */ + ZIP(u)[0] = (struct Ziphuft *)NULL; /* just to keep compilers happy */ + q = (struct Ziphuft *)NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = ZIP(c)[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l[h]) + { + w += l[h++]; /* add bits already decoded */ + + /* compute minimum size table less than or equal to *m bits */ + z = (z = g - w) > (cab_ULONG)*m ? *m : z; /* upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = ZIP(c) + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + if ((cab_ULONG)w + j > el && (cab_ULONG)w < el) + j = el - w; /* make EOB code end at table */ + z = 1 << j; /* table entries for j-bit table */ + l[h] = j; /* set table size in stack */ + + /* allocate and link in new table */ + if (!(q = (struct Ziphuft *) malloc((z + 1)*sizeof(struct Ziphuft)))) + { + if(h) + Ziphuft_free(ZIP(u)[0]); + return 3; /* not enough memory */ + } + *t = q + 1; /* link to list for Ziphuft_free() */ + *(t = &(q->v.t)) = (struct Ziphuft *)NULL; + ZIP(u)[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) + { + ZIP(x)[h] = i; /* save pattern for backing up */ + r.b = (cab_UBYTE)l[h-1]; /* bits to dump before this table */ + r.e = (cab_UBYTE)(16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = (i & ((1 << w) - 1)) >> (w - l[h-1]); + ZIP(u)[h-1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.b = (cab_UBYTE)(k - w); + if (p >= ZIP(v) + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (cab_UBYTE)(*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = *p++; /* simple code is just the value */ + } + else + { + r.e = (cab_UBYTE)e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != ZIP(x)[h]) + w -= l[--h]; /* don't need to update q */ + } + } + + /* return actual size of base table */ + *m = l[0]; + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + +/********************************************************* + * Zipinflate_codes (internal) + */ +cab_LONG Zipinflate_codes(struct Ziphuft *tl, struct Ziphuft *td, + cab_LONG bl, cab_LONG bd, cab_decomp_state *decomp_state) +{ + register cab_ULONG e; /* table entry flag/number of extra bits */ + cab_ULONG n, d; /* length and index for copy */ + cab_ULONG w; /* current window position */ + struct Ziphuft *t; /* pointer to table entry */ + cab_ULONG ml, md; /* masks for bl and bd bits */ + register cab_ULONG b; /* bit buffer */ + register cab_ULONG k; /* number of bits in bit buffer */ + + /* make local copies of globals */ + b = ZIP(bb); /* initialize bit buffer */ + k = ZIP(bk); + w = ZIP(window_posn); /* initialize window position */ + + /* inflate the coded data */ + ml = Zipmask[bl]; /* precompute masks for speed */ + md = Zipmask[bd]; + + for(;;) + { + ZIPNEEDBITS((cab_ULONG)bl) + if((e = (t = tl + ((cab_ULONG)b & ml))->e) > 16) + do + { + if (e == 99) + return 1; + ZIPDUMPBITS(t->b) + e -= 16; + ZIPNEEDBITS(e) + } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16); + ZIPDUMPBITS(t->b) + if (e == 16) /* then it's a literal */ + CAB(outbuf)[w++] = (cab_UBYTE)t->v.n; + else /* it's an EOB or a length */ + { + /* exit if end of block */ + if(e == 15) + break; + + /* get length of block to copy */ + ZIPNEEDBITS(e) + n = t->v.n + ((cab_ULONG)b & Zipmask[e]); + ZIPDUMPBITS(e); + + /* decode distance of block to copy */ + ZIPNEEDBITS((cab_ULONG)bd) + if ((e = (t = td + ((cab_ULONG)b & md))->e) > 16) + do { + if (e == 99) + return 1; + ZIPDUMPBITS(t->b) + e -= 16; + ZIPNEEDBITS(e) + } while ((e = (t = t->v.t + ((cab_ULONG)b & Zipmask[e]))->e) > 16); + ZIPDUMPBITS(t->b) + ZIPNEEDBITS(e) + d = w - t->v.n - ((cab_ULONG)b & Zipmask[e]); + ZIPDUMPBITS(e) + do + { + n -= (e = (e = ZIPWSIZE - ((d &= ZIPWSIZE-1) > w ? d : w)) > n ?n:e); + do + { + CAB(outbuf)[w++] = CAB(outbuf)[d++]; + } while (--e); + } while (n); + } + } + + /* restore the globals from the locals */ + ZIP(window_posn) = w; /* restore global window pointer */ + ZIP(bb) = b; /* restore global bit buffer */ + ZIP(bk) = k; + + /* done */ + return 0; +} + +/*********************************************************** + * Zipinflate_stored (internal) + */ +cab_LONG Zipinflate_stored(cab_decomp_state *decomp_state) +/* "decompress" an inflated type 0 (stored) block. */ +{ + cab_ULONG n; /* number of bytes in block */ + cab_ULONG w; /* current window position */ + register cab_ULONG b; /* bit buffer */ + register cab_ULONG k; /* number of bits in bit buffer */ + + /* make local copies of globals */ + b = ZIP(bb); /* initialize bit buffer */ + k = ZIP(bk); + w = ZIP(window_posn); /* initialize window position */ + + /* go to byte boundary */ + n = k & 7; + ZIPDUMPBITS(n); + + /* get the length and its complement */ + ZIPNEEDBITS(16) + n = ((cab_ULONG)b & 0xffff); + ZIPDUMPBITS(16) + ZIPNEEDBITS(16) + if (n != (cab_ULONG)((~b) & 0xffff)) + return 1; /* error in compressed data */ + ZIPDUMPBITS(16) + + /* read and output the compressed data */ + while(n--) + { + ZIPNEEDBITS(8) + CAB(outbuf)[w++] = (cab_UBYTE)b; + ZIPDUMPBITS(8) + } + + /* restore the globals from the locals */ + ZIP(window_posn) = w; /* restore global window pointer */ + ZIP(bb) = b; /* restore global bit buffer */ + ZIP(bk) = k; + return 0; +} + +/****************************************************** + * Zipinflate_fixed (internal) + */ +cab_LONG Zipinflate_fixed(cab_decomp_state *decomp_state) +{ + struct Ziphuft *fixed_tl; + struct Ziphuft *fixed_td; + cab_LONG fixed_bl, fixed_bd; + cab_LONG i; /* temporary variable */ + cab_ULONG *l; + + l = ZIP(ll); + + /* literal table */ + for(i = 0; i < 144; i++) + l[i] = 8; + for(; i < 256; i++) + l[i] = 9; + for(; i < 280; i++) + l[i] = 7; + for(; i < 288; i++) /* make a complete, but wrong code set */ + l[i] = 8; + fixed_bl = 7; + if((i = Ziphuft_build(l, 288, 257, (cab_UWORD *) Zipcplens, + (cab_UWORD *) Zipcplext, &fixed_tl, &fixed_bl, decomp_state))) + return i; + + /* distance table */ + for(i = 0; i < 30; i++) /* make an incomplete code set */ + l[i] = 5; + fixed_bd = 5; + if((i = Ziphuft_build(l, 30, 0, (cab_UWORD *) Zipcpdist, (cab_UWORD *) Zipcpdext, + &fixed_td, &fixed_bd, decomp_state)) > 1) + { + Ziphuft_free(fixed_tl); + return i; + } + + /* decompress until an end-of-block code */ + i = Zipinflate_codes(fixed_tl, fixed_td, fixed_bl, fixed_bd, decomp_state); + + Ziphuft_free(fixed_td); + Ziphuft_free(fixed_tl); + return i; +} + +/************************************************************** + * Zipinflate_dynamic (internal) + */ +cab_LONG Zipinflate_dynamic(cab_decomp_state *decomp_state) + /* decompress an inflated type 2 (dynamic Huffman codes) block. */ +{ + cab_LONG i; /* temporary variables */ + cab_ULONG j; + cab_ULONG *ll; + cab_ULONG l; /* last length */ + cab_ULONG m; /* mask for bit lengths table */ + cab_ULONG n; /* number of lengths to get */ + struct Ziphuft *tl; /* literal/length code table */ + struct Ziphuft *td; /* distance code table */ + cab_LONG bl; /* lookup bits for tl */ + cab_LONG bd; /* lookup bits for td */ + cab_ULONG nb; /* number of bit length codes */ + cab_ULONG nl; /* number of literal/length codes */ + cab_ULONG nd; /* number of distance codes */ + register cab_ULONG b; /* bit buffer */ + register cab_ULONG k; /* number of bits in bit buffer */ + + /* make local bit buffer */ + b = ZIP(bb); + k = ZIP(bk); + ll = ZIP(ll); + + /* read in table lengths */ + ZIPNEEDBITS(5) + nl = 257 + ((cab_ULONG)b & 0x1f); /* number of literal/length codes */ + ZIPDUMPBITS(5) + ZIPNEEDBITS(5) + nd = 1 + ((cab_ULONG)b & 0x1f); /* number of distance codes */ + ZIPDUMPBITS(5) + ZIPNEEDBITS(4) + nb = 4 + ((cab_ULONG)b & 0xf); /* number of bit length codes */ + ZIPDUMPBITS(4) + if(nl > 288 || nd > 32) + return 1; /* bad lengths */ + + /* read in bit-length-code lengths */ + for(j = 0; j < nb; j++) + { + ZIPNEEDBITS(3) + ll[Zipborder[j]] = (cab_ULONG)b & 7; + ZIPDUMPBITS(3) + } + for(; j < 19; j++) + ll[Zipborder[j]] = 0; + + /* build decoding table for trees--single level, 7 bit lookup */ [truncated at 1000 lines; 5421 more skipped]