📄 lzhtool.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 + -