⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lzexpand_main.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: lzexpand_main.c 25633 2007-01-26 07:22:19Z ion $
 *
 * LZ Decompression functions
 *
 * Copyright 1996 Marcus Meissner
 *
 * 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
 */
/*
 * FIXME: return values might be wrong
 */

//#include "config.h"

#include <k32.h>
#define NDEBUG
#include "../include/debug.h"
#include "lzexpand.h"

#define HFILE_ERROR ((HFILE)-1)

/* The readahead length of the decompressor. Reading single bytes
 * using _hread() would be SLOW.
 */
#define	GETLEN	2048

/* Format of first 14 byte of LZ compressed file */
struct lzfileheader {
	BYTE	magic[8];
	BYTE	compressiontype;
	CHAR	lastchar;
	DWORD	reallength;
};
static BYTE LZMagic[8]={'S','Z','D','D',0x88,0xf0,0x27,0x33};

struct lzstate {
	HFILE	realfd;		/* the real filedescriptor */
	CHAR	lastchar;	/* the last char of the filename */

	DWORD	reallength;	/* the decompressed length of the file */
	DWORD	realcurrent;	/* the position the decompressor currently is */
	DWORD	realwanted;	/* the position the user wants to read from */

	BYTE	table[0x1000];	/* the rotating LZ table */
	UINT	curtabent;	/* CURrent TABle ENTry */

	BYTE	stringlen;	/* length and position of current string */
	DWORD	stringpos;	/* from stringtable */


	WORD	bytetype;	/* bitmask within blocks */

	BYTE	*get;		/* GETLEN bytes */
	DWORD	getcur;		/* current read */
	DWORD	getlen;		/* length last got */
};

#define MAX_LZSTATES 16
static struct lzstate *lzstates[MAX_LZSTATES];

#define IS_LZ_HANDLE(h) (((h) >= 0x400) && ((h) < 0x400+MAX_LZSTATES))
#define GET_LZ_STATE(h) (IS_LZ_HANDLE(h) ? lzstates[(h)-0x400] : NULL)

/* reads one compressed byte, including buffering */
#define GET(lzs,b)	_lzget(lzs,&b)
#define GET_FLUSH(lzs)	lzs->getcur=lzs->getlen;

static int
_lzget(struct lzstate *lzs,BYTE *b) {
	if (lzs->getcur<lzs->getlen) {
		*b		= lzs->get[lzs->getcur++];
		return		1;
	} else {
		int ret = _hread(lzs->realfd,lzs->get,GETLEN);
		if (ret==HFILE_ERROR)
			return HFILE_ERROR;
		if (ret==0)
			return 0;
		lzs->getlen	= ret;
		lzs->getcur	= 1;
		*b		= *(lzs->get);
		return 1;
	}
}
/* internal function, reads lzheader
 * returns BADINHANDLE for non filedescriptors
 * return 0 for file not compressed using LZ
 * return UNKNOWNALG for unknown algorithm
 * returns lzfileheader in *head
 */
static INT read_header(HFILE fd,struct lzfileheader *head)
{
	BYTE	buf[14];

	if (_llseek(fd,0,SEEK_SET)==-1)
		return LZERROR_BADINHANDLE;

	/* We can't directly read the lzfileheader struct due to
	 * structure element alignment
	 */
	if (_hread(fd,buf,14)<14)
		return 0;
	memcpy(head->magic,buf,8);
	memcpy(&(head->compressiontype),buf+8,1);
	memcpy(&(head->lastchar),buf+9,1);

	/* FIXME: consider endianess on non-intel architectures */
	memcpy(&(head->reallength),buf+10,4);

	if (memcmp(head->magic,LZMagic,8))
		return 0;
	if (head->compressiontype!='A')
		return LZERROR_UNKNOWNALG;
	return 1;
}


/***********************************************************************
 *           LZStart   (LZ32.@)
 *
 * @unimplemented
 */
INT WINAPI LZStart(void)
{
    DPRINT("(void)\n");
    return 1;
}


/***********************************************************************
 *           LZInit   (LZ32.@)
 *
 * initializes internal decompression buffers, returns lzfiledescriptor.
 * (return value the same as hfSrc, if hfSrc is not compressed)
 * on failure, returns error code <0
 * lzfiledescriptors range from 0x400 to 0x410 (only 16 open files per process)
 *
 * since _llseek uses the same types as libc.lseek, we just use the macros of
 *  libc
 *
 * @implemented
 */
HFILE WINAPI LZInit( HFILE hfSrc )
{

	struct	lzfileheader	head;
	struct	lzstate		*lzs;
	DWORD	ret;
        int i;

	DPRINT("(%d)\n",hfSrc);
	ret=read_header(hfSrc,&head);
	if (ret<=0) {
		_llseek(hfSrc,0,SEEK_SET);
		return ret?(HFILE)ret:hfSrc;
	}
        for (i = 0; i < MAX_LZSTATES; i++) if (!lzstates[i]) break;
        if (i == MAX_LZSTATES) return LZERROR_GLOBALLOC;
	lzstates[i] = lzs = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(struct lzstate) );
	if(lzs == NULL) return LZERROR_GLOBALLOC;

	memset(lzs,'\0',sizeof(*lzs));
	lzs->realfd	= hfSrc;
	lzs->lastchar	= head.lastchar;
	lzs->reallength = head.reallength;

	lzs->get	= RtlAllocateHeap( GetProcessHeap(), 0, GETLEN );
	lzs->getlen	= 0;
	lzs->getcur	= 0;

	if(lzs->get == NULL) {
		RtlFreeHeap(GetProcessHeap(), 0, lzs);
		lzstates[i] = NULL;
		return LZERROR_GLOBALLOC;
	}

	/* Yes, preinitialize with spaces */
	memset(lzs->table,' ',0x1000);
	/* Yes, start 16 byte from the END of the table */
	lzs->curtabent	= 0xff0;
	return 0x400 + i;
}


/***********************************************************************
 *           LZDone   (LZEXPAND.9)
 *           LZDone   (LZ32.@)
 *
 * @unimplemented
 */
void WINAPI LZDone(void)
{
    DPRINT("(void)\n");
}


/***********************************************************************
 *           GetExpandedNameA   (LZ32.@)
 *
 * gets the full filename of the compressed file 'in' by opening it
 * and reading the header
 *
 * "file." is being translated to "file"
 * "file.bl_" (with lastchar 'a') is being translated to "file.bla"
 * "FILE.BL_" (with lastchar 'a') is being translated to "FILE.BLA"
 *
 * @implemented
 */

INT WINAPI GetExpandedNameA( LPSTR in, LPSTR out )
{
	struct lzfileheader	head;
	HFILE		fd;
	OFSTRUCT	ofs;
	INT		fnislowercased,ret,len;
	LPSTR		s,t;

	DPRINT("(%s)\n",in);
	fd=OpenFile(in,&ofs,OF_READ);
	if (fd==HFILE_ERROR)
		return (INT)(INT16)LZERROR_BADINHANDLE;
	strcpy(out,in);
	ret=read_header(fd,&head);
	if (ret<=0) {
		/* not a LZ compressed file, so the expanded name is the same
		 * as the input name */
		_lclose(fd);
		return 1;
	}


	/* look for directory prefix and skip it. */
	s=out;
	while (NULL!=(t=strpbrk(s,"/\\:")))
		s=t+1;

	/* now mangle the basename */
	if (!*s) {
		/* FIXME: hmm. shouldn't happen? */
		DPRINT("Specified a directory or what? (%s)\n",in);
		_lclose(fd);
		return 1;
	}
	/* see if we should use lowercase or uppercase on the last char */
	fnislowercased=1;
	t=s+strlen(s)-1;
	while (t>=out) {
		if (!isalpha(*t)) {
			t--;
			continue;
		}
		fnislowercased=islower(*t);
		break;
	}
	if (isalpha(head.lastchar)) {
		if (fnislowercased)
			head.lastchar=(CHAR)tolower(head.lastchar);
		else
			head.lastchar=(CHAR)toupper(head.lastchar);
	}

	/* now look where to replace the last character */
	if (NULL!=(t=strchr(s,'.'))) {
		if (t[1]=='\0') {
			t[0]='\0';
		} else {
			len=strlen(t)-1;
			if (t[len]=='_')
				t[len]=head.lastchar;
		}
	} /* else no modification necessary */
	_lclose(fd);
	return 1;
}


/***********************************************************************
 *           GetExpandedNameW   (LZ32.@)
 *
 * @implemented
 */
INT WINAPI GetExpandedNameW( LPWSTR in, LPWSTR out )
{
    INT ret;
    DWORD len;
    char *xin, *xout;
    len = WideCharToMultiByte( CP_ACP, 0, in, -1, NULL, 0, NULL, NULL );
    xin = RtlAllocateHeap( RtlGetProcessHeap(), 0, len );
    if (xin == NULL)
        return LZERROR_BADVALUE;
    xout = RtlAllocateHeap( RtlGetProcessHeap(), 0, len+3 );
    if (xout == NULL)
    {
        RtlFreeHeap( RtlGetProcessHeap(), 0, xin );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -