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

📄 lzhtool.cpp

📁 一个解压程序,只要设定了解压路径和解压文件的种类,就可以随意解压
💻 CPP
字号:

#include "stdafx.h"
#include "LzhTool.h"
#include "LzhDecoder2.h"

bool CLzhTool::Check( const char* fname, unsigned long fsize )
{
	const unsigned char* hdr = CTool::common_buf;
	unsigned long siz = (fsize>XACR_BUFSIZE ? XACR_BUFSIZE : fsize);
//--------------------------------------------------------------------//

	return (-1!=FindHeader(fname,hdr,siz>300*1024?300*1024:siz));
}

bool CLzhTool::Extract( const char* fname,const char* ddir )
{
	// 愭摢偺曽傪撉傒崬傒
	FILE* fp = fopen( fname,"rb" );
	if( !fp )
		return false;
	DWORD siz = fread( CTool::common_buf, 1, XACR_BUFSIZE, fp );
	fclose( fp );
	// 僿僢僟傪扵偡
	int ps = FindHeader( fname,CTool::common_buf,siz );
	if( ps==-1 )
		return false;

	// 彂屔傪奐偔
	if( !(lzh = fopen( fname,"rb" )) )
		return false;
	fseek( lzh,ps,SEEK_SET );

	// 奿擺僼傽僀儖枅偵張棟
	while( ReadHeader( CTool::common_buf ) )
	{
		long base = ftell( lzh );
//		char* name;
		char name[MAX_PATH];
//		TCHAR t_name[MAX_PATH];
		TCHAR* t_name;
		
		sprintf(name, "%s\\%s", ueutil::GetExtractPath(), kiutil::pathMake(h_FileName)); //by uema2.

//		if( out=fopen( name=kiutil::pathMake(h_FileName),"wb") )
		if( out=fopen( name,"wb") )
		{
			// 僨僐乕僪
			CLzhDecoder2 dec;
//			lzh_method mhd = UNKNOWN;
			lzh_method mhd = _UNKNOWN;
				 if( 0==strcmp(h_Method,"-lh0-") )mhd=LH0;
			else if( 0==strcmp(h_Method,"-lh1-") )mhd=LH1;
			else if( 0==strcmp(h_Method,"-lh2-") )mhd=LH2;
			else if( 0==strcmp(h_Method,"-lh3-") )mhd=LH3;
			else if( 0==strcmp(h_Method,"-lh5-") )mhd=LH5;
			else if( 0==strcmp(h_Method,"-lh6-") )mhd=LH6;
			else if( 0==strcmp(h_Method,"-lh7-") )mhd=LH7;
			else if( 0==strcmp(h_Method,"-lzs-") )mhd=LZS;
			else if( 0==strcmp(h_Method,"-lz4-") )mhd=LZ4;
			else if( 0==strcmp(h_Method,"-lz5-") )mhd=LZ5;
			dec.Decode( mhd, lzh, h_CompSize, out, h_OrigSize );

			// 懏惈側偳愝掕
			fclose( out );

			//name傪t_name(TCHAR)偵 by uema2.
			t_name = (TCHAR*)LocalAlloc(LPTR, (strlen(name)+1)*sizeof(TCHAR));
			_MultiByteToWideChar(CP_ACP, 0, name, strlen(name)+1,
				t_name, strlen(name)+1);
//			SetFileAttributes( name,h_Attrib );
			SetFileAttributes( t_name,h_Attrib ); //fixed by uema2.
			LocalFree(t_name);

			if( h_Level<2 )
				kiutil::timeSet(name,(WORD)(h_Update>>16),(WORD)h_Update);
			else
				kiutil::timeSet( name, h_Update );

		}

		fseek( lzh, base+h_CompSize, SEEK_SET );
	}

    fclose( lzh );
	return true;
}

int CLzhTool::FindHeader( const char* fname, const BYTE* hdr, DWORD siz )
{
	bool bopen = false;
	BYTE* temp;
	int ans=-1;

	for( DWORD i=0; i<siz-20; i++ )
	{
		if( hdr[i+2]=='-' && hdr[i+3]=='l' &&
		   (hdr[i+4]=='h' || hdr[i+4]=='z') )
		{
			if( !bopen )
				if( !(lzh=fopen( fname,"rb" )) )
					return -1;
				else
					temp = new BYTE[65536];

			fseek( lzh,i,SEEK_SET );
			if( ReadHeader(temp) )
				{ans=(signed)i;break;}
		}
	}

	if( bopen )
		{delete [] temp;fclose( lzh );}
	return ans;
}

bool CLzhTool::ReadHeader( unsigned char* buf )
{
// 弶婜壔
	*h_FileName=0;
	sum=0,crc=0;

// 偩偄偨偄嫟捠側晹暘
//
//  0- 1: [0]=header_size [1]=check_sum (h0)
//        [0]=bas_hdr_siz [1]=check_sum (h1)
//        [WORD] = all_header_size      (h2)
//
//  2- 6: method
//
//  7-10: [DWORD]=compressed_size (h0/h2)
//        [DWORD]=offset_to_next_hdr (h1)
//
// 11-14: [DWORD]=original_size
//
// 15-18: [ftime]=update_date_time
//
//    19: attribute (h0)
//        0x20      (h1/h2)
//
//    20: header_level
//
	if( 21!=fread_crc(buf,21) )
		return false;
	sum-=(buf[0]+buf[1]);

	if( (h_Level=buf[20])>2 ) // LV3埲忋枹懳墳
		return false;

	BYTE bshdr = (h_Level==2)?26:buf[0]+2;
	if( bshdr<21 || buf[0]==0 )
		return false;
	BYTE hdrsum= buf[1];
	for( int i=0; i!=5; i++ )
		h_Method[i]=(char)buf[2+i];h_Method[5]=0;
	h_CompSize = (buf[ 7])+(buf[ 8]<<8)+(buf[ 9]<<16)+(buf[10]<<24);
	h_OrigSize = (buf[11])+(buf[12]<<8)+(buf[13]<<16)+(buf[14]<<24);
	h_Update   = (buf[15])+(buf[16]<<8)+(buf[17]<<16)+(buf[18]<<24);
	h_Attrib   =  buf[19];
	if( h_Method[0]!='-' || h_Method[1]!='l' )
		return false;

// 儗儀儖嫟捠偠傖側偄婎杮僿僢僟晹暘
// <h0>
//     21: file_name_length
//  22- n: file_name ( with path info )
//   WORD: crc16_of_file
//       : and some extension part
//
// <h1>
//     21: file_name_length
//  22- n: file_name ( with no path info )
//   WORD: crc16_of_file
//   BYTE: os_flag
//       : and some extension part
//
// <h2>
//   WORD: crc16_of_file
//   BYTE: os_flag
//
//
	if( (bshdr-21)!=fread_crc(buf+21,(bshdr-21)) )
		return false;
	if( h_Level!=2 )
	{
		if( sum!=hdrsum || 21+1+buf[21]+2>bshdr )
			return false;
		memcpy( h_FileName,buf+22,buf[21] );
		h_FileName[buf[21]]=0;
	}

// 奼挘僿僢僟( h1/h2 )
//  repeating of such blocks.
//------------------------------------------------------
//  WORD: size_of_this_block ( if 0 then end_of_header )
//  BYTE: type_flag
//      : data ( (blocksize-3) bytes )
//------------------------------------------------------

	char PathName[MAX_PATH*2]={0};
	if( h_Level!=0 )
	{
		DWORD hdrcrc=0xffffffff;
		WORD tmpcrc;

		// 偙偙偱儖乕僾偭偰奼挘僿僢僟撉傒崬傒
		WORD ehs;
		ehs = ((buf[bshdr-2])|(buf[bshdr-1]<<8));

		while( ehs>2 )
		{
			tmpcrc=crc;//CRC帺恎傪撉傒崬傫偩偲偒偵捈偡偨傔
			if( ehs!=fread_crc(buf,ehs) )
				return false;
			if( h_Level==1 )
				h_CompSize-=ehs;

			switch( *buf )
			{
			case 0x00://嫟捠
				if( ehs>=5 && hdrcrc==0xffffffff )
				{
					hdrcrc=((buf[1])|(buf[2]<<8));

					crc=tmpcrc;
					buf[1]=buf[2]=0;
					UpdateCRC(buf,ehs);
				}
				break;
			case 0x01://僼傽僀儖柤
				memcpy(h_FileName,buf+1,ehs-3>MAX_PATH?MAX_PATH:ehs-3);
				h_FileName[ehs-3>MAX_PATH?MAX_PATH:ehs-3]=0;
				break;
			case 0x02://僷僗柤
				memcpy(PathName,buf+1,ehs-3>MAX_PATH?MAX_PATH:ehs-3);
				PathName[ehs-3>MAX_PATH?MAX_PATH:ehs-3]=0;
				break;
			case 0xff://怴懏惈
				break;
			case 0x40://懏惈(DOS埶懚)
				if( ehs>=5 )
					h_Attrib=((buf[1])|(buf[2]<<8));
				break;
			case 0x41://僞僀儉僗僞儞僾(UNLHA32.DLL)
				//偼丄側傫偩偐偆傑偔偄偐側偄偺偱柍帇偡傞丅
				break;
			}

			ehs = ((buf[ehs-2])|(buf[ehs-1]<<8));
		}

		if( hdrcrc!=0xffffffff && crc!=hdrcrc )
			return false;
	}

	// ff -> \\ 曄姺
	// CE偼CharNext偼Unicode側偺偱丄Char梡CharNext傪嶌偭偨 by uema2.
	char* x;
	for( x=h_FileName; *x!=0; x=ueutil::CharNext(x) )
		if( (BYTE)*x==0xff )
			*x='\\';
	for( x=PathName; *x!=0; x=ueutil::CharNext(x) )
		if( (BYTE)*x==0xff )
			*x='\\';

	strcat( PathName,h_FileName );
	strcpy( h_FileName,PathName );
	return true;

// lha header MEMO
// (h0/h1)
//   1 byte 栚偼丄乽1byte栚帺恎傪彍偄偨婎杮僿僢僟偺僒僀僘乿
//   僠僃僢僋僒儉偼丄乽1,2byte栚帺恎傪彍偄偨婎杮僿僢僟偺崌寁乿
// (h1)
//   offset_to_next_hdr 偼丄婎杮僿僢僟枛抂偐傜師偺僿僢僟傊偺嫍棧
// (h1/h2)
//   crc偼帺暘帺恎偼0000偲偟偰懠慡晹偐傜嶼弌
}

⌨️ 快捷键说明

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