📄 imptool.cpp
字号:
#include "stdafx.h"
#include "ImpTool.h"
/*IMP_DIR_ENTRY flags*/
#define DFLAG_DIR 1
#define DFLAG_E8SHORT 2
#define DFLAG_E8LONG 4
/*IMP_HEADER flags*/
#define HFLAG_MULTIVOL 1
#define HFLAG_LASTVOL 2
#define HFLAG_BLOWFISH 4
/*methods*/
#define METHOD_STORE 0
#define METHOD_LZ77 1
#define METHOD_BWT 2
#define METHOD_LZ77_MM 3
/*LZ77*/
#define NLLCODES 288 /* Number of literal-length codes */
#define NDCODES 42 /* Number of distance codes */
#define ND2CODES 14 /* Number of distance codes for length==2 */
#define ND3CODES 28 /* Number of distance codes for length==3 */
#define MIN_LZ_CODES (NLLCODES+NDCODES+ND2CODES)
#define LONGMATCHBITS 15 /*extra bits for long match*/
#define LONGMATCHMASK ((1<<LONGMATCHBITS)-1)
#define LONGMATCHCODE (NLLCODES-2)
#define MMCODE (NLLCODES-1) /*multimedia code*/
#define LLTTBITS 9
#define DTTBITS 7
#define LLTTSIZE (1<<LLTTBITS)
#define DTTSIZE (1<<DTTBITS)
#define MAX_MM_CODES 1024
/*BWT*/
#define NCODES 258
#define WINDOW 50
#define BWTABLES 6
#define BWTTBITS 9
#define BWTTSIZE (1<<BWTTBITS)
#define MAX_NCODES NLLCODES
#define MAXCODELEN 16
#define NLENCODES (MAXCODELEN+5) /* no. of code length codes */
#define ZRUN (MAXCODELEN+1) /* run of zeros */
#define DZRUN (MAXCODELEN+3)/* run of delta-zeros*/
#define HC_MCL 14 /* max code length for storing Huffman codes */
#define HCTTBITS 6
#define HCTTSIZE (1<<HCTTBITS)
#define USEDBITS(n) {bitpos-=n;bitbuf>>=n;}
//////////////////////////////////////////////////////////////
bool CImpTool::Check( const char* fname, unsigned long fsize )
{
const unsigned char* hdr = CTool::common_buf;
unsigned long siz = (fsize>XACR_BUFSIZE ? XACR_BUFSIZE : fsize);
//--------------------------------------------------------------------//
// 彫偝偡偓
if( siz<IMP_HEADER_SIZE )
return false;
// IMP側傜CRC僠僃僢僋
if( hdr[0]=='I' && hdr[1]=='M' && hdr[2]=='P' && hdr[3]=='\n' )
return HeaderCheck( hdr );
// EXE側傜僿僢僟扵偟
if( hdr[0]=='M' && hdr[1]=='Z' )
{
const unsigned char* src = hdr+2;
const unsigned char* end
= hdr+(siz>32768 ? 32768 : siz)-IMP_HEADER_SIZE+1;
do
{
while(src!=end)
if( *(src++)=='I' )
break;
if( src==end )return false;
if( src[0]=='M' && src[1]=='P' && src[2]=='\n' )
if( HeaderCheck(src-1) )
return true;
src++;
}while( src<end );
return false;
}
return false;
}
bool CImpTool::Extract( const char* fname,const char* ddir )
{
imp = fopen(fname,"rb");
if( imp==NULL )return false;
if( !ReadImpHead() )
{fclose(imp);return false;}
if(ih.flags&HFLAG_MULTIVOL)
{fclose(imp);return false;}
if(ih.flags&HFLAG_BLOWFISH)
{fclose(imp);return false;}
g_blockbuffer=0;g_prevfpos=0xffffffff;
dirbufsrc = dirbufend = dirbuf;
char outname[MAX_PATH], *name;
char tmpname[MAX_PATH]; //by uema2.
IMP_DIR_ENTRY dirent;
for( unsigned long ent=0; ent!=ih.direntries; ent++ )
{
if( !get_dir_entry(&dirent,outname) )
return false;
sprintf(tmpname, "%s\\%s", ueutil::GetExtractPath(),
name=kiutil::pathMake(outname)); // by uema2.
strcpy(name, tmpname);
// name = kiutil::pathMake( outname );
if( dirent.flags&DFLAG_DIR )continue;
out = fopen( name,"wb" );
if( !out ) continue;
decomp( out, dirent.fpos,
dirent.unitpos, dirent.esize, dirent.flags );
fclose( out );
kiutil::timeSet( name,(WORD)(dirent.mdate),(WORD)dirent.mtime );
//name傪t_name(TCHAR)偵 by uema2.
TCHAR *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,dirent.attrib );
SetFileAttributes( t_name,dirent.attrib );
LocalFree(t_name);
}
return true;
}
/********************************/
static const int g_ncodes[3]={NDCODES,ND2CODES,ND3CODES},
g_ncoffset[3]={NLLCODES,NLLCODES+NDCODES,NLLCODES+NDCODES+ND2CODES};
static const unsigned long g_overlaps[3][8]=
{{32768,65536,73728,98304,122880,147456,172032,196608}, /*normal*/
{32768,65536,73728,98304,122880,147456,172032,196608}, /*normal*/
{32768,131072,196608,262144,327680,393216,458752,524288}}; /*best*/
bool CImpTool::ReadImpHead()
{
unsigned char ihbuf[IMP_HEADER_SIZE];
g_exesize=0;
// 僿僢僟暘撉傓
if( IMP_HEADER_SIZE!=fread(ihbuf,1,IMP_HEADER_SIZE,imp) )
return false;
// IMP側傜CRC僠僃僢僋
if( ihbuf[0]=='I' && ihbuf[1]=='M' && ihbuf[2]=='P' && ihbuf[3]=='\n' )
{if( !HeaderCheck(ihbuf) )return false;}
// EXE側傜僿僢僟扵偟
else if( ihbuf[0]=='M' && ihbuf[1]=='Z' )
{
unsigned char *buffer=new unsigned char[32768],*src,*end;
int nread = fread(buffer,1,32768,imp);
if( nread<IMP_HEADER_SIZE )return false;
src=buffer;
end=buffer+nread-IMP_HEADER_SIZE+1;
do
{
while(src!=end)
if( *(src++)=='I' )
break;
if( src==end )return false;
if( src[0]=='M' && src[1]=='P' && src[2]=='\n' )
if( HeaderCheck(src-1) )
{
g_exesize = src-1-buffer+IMP_HEADER_SIZE;
memcpy(ihbuf,src-1,IMP_HEADER_SIZE);
break;
}
src++;
}while( src<end );
if( src>=end )return false;
delete [] buffer;
}
// 偱側偗傝傖幐攕
else
return false;
// 撉傓
ih.diroffset = ihbuf[ 4] + (ihbuf[ 5]<<8) + (ihbuf[ 6]<<16) + (ihbuf[ 7]<<24);
ih.direntries= ihbuf[ 8] + (ihbuf[ 9]<<8) + (ihbuf[10]<<16) + (ihbuf[11]<<24);
ih.cmoffset = ihbuf[16] + (ihbuf[17]<<8) + (ihbuf[18]<<16) + (ihbuf[19]<<24);
ih.flags = ihbuf[38] + (ihbuf[39]<<8);
ih.crc = ihbuf[40] + (ihbuf[41]<<8);
dirfpos=ih.diroffset+g_exesize;
return true;
}
bool CImpTool::HeaderCheck(const unsigned char* p)
{
const unsigned char dm[2]={0,0};
DWORD crc=0xffffffff;
crc = calc_crc( p,40,crc );
crc = calc_crc( dm,2,crc );
return ((~crc)&0xffff) == (unsigned)(p[40]|(p[41]<<8));
}
bool CImpTool::get_dir_entry( IMP_DIR_ENTRY *pdirent,char *name )
{
if( dirbufsrc >= dirbufend )
if( !extract_dir() )
return false;
if( dirbufend-dirbufsrc<IMP_DIR_ENTRY_SIZE )
return false;
pdirent->ver = dirbufsrc[0] + (dirbufsrc[1]<<8);
pdirent->fpos = dirbufsrc[4] + (dirbufsrc[5]<<8) + (dirbufsrc[6]<<16) + (dirbufsrc[7]<<24);
pdirent->commlen= dirbufsrc[10];
pdirent->flags = dirbufsrc[11];
pdirent->unitpos= dirbufsrc[12] + (dirbufsrc[13]<<8) + (dirbufsrc[14]<<16) + (dirbufsrc[15]<<24);
pdirent->esize = dirbufsrc[16] + (dirbufsrc[17]<<8) + (dirbufsrc[18]<<16) + (dirbufsrc[19]<<24);
pdirent->crc = dirbufsrc[20] + (dirbufsrc[21]<<8) + (dirbufsrc[22]<<16) + (dirbufsrc[23]<<24);
pdirent->extra = dirbufsrc[24] + (dirbufsrc[25]<<8);
pdirent->namelen= dirbufsrc[26] + (dirbufsrc[27]<<8);
pdirent->mtime = dirbufsrc[32] + (dirbufsrc[33]<<8);
pdirent->mdate = dirbufsrc[34] + (dirbufsrc[35]<<8);
pdirent->entcrc = dirbufsrc[36] + (dirbufsrc[37]<<8);
if( (pdirent->ver&0xfff)>0x10A/*MAX_VERSION*/ )
return false;
int i=IMP_DIR_ENTRY_SIZE+pdirent->namelen+pdirent->commlen+pdirent->extra;
if( dirbufend-dirbufsrc<i )
return false;
dirbufsrc[36]=0;
dirbufsrc[37]=0;
if( (~calc_crc(dirbufsrc,i,0xffffffff)&0xffff)!=pdirent->entcrc )
return false;
memcpy( name,dirbufsrc+IMP_DIR_ENTRY_SIZE,pdirent->namelen );
name[ pdirent->namelen ]=0;
// for(char*p=name;*p;p=CharNext(p))if(*p=='/')*p='\\';
for(char*p=name;*p;p=ueutil::CharNext(p))if(*p=='/')*p='\\'; // by uema2.
dirbufsrc+=i;
return true;
}
bool CImpTool::extract_dir()
{
int i,method;
unsigned long csize,exsize;
unsigned char sig[6];
static const unsigned char dirsig[]={0x49,0x4D,0x50,0x44,0x45,0};
unsigned long fpos=ftell(imp);
fseek( imp,dirfpos,SEEK_SET );
dirbufsrc=dirbuf;
dirbufend=dirbuf;
if( 6!=fread(sig,1,6,imp) ) return false;
if( 0!=memcmp(sig,&dirsig,6) ) return false;
init_getbits();
method=getbits(5)&15;
USEDBITS(5);
if(method>METHOD_LZ77)return false;
exsize=getbits(20)&((1L<<20)-1);
USEDBITS(20);
if(exsize>8192)return false;
csize=getbits(20)&((1L<<20)-1);
USEDBITS(20);
if(method==METHOD_LZ77)
{
USEDBITS(5);
i=expand_lz((unsigned char*)dirbuf,0,exsize,0);
}
else i=unstore((unsigned char*)dirbuf,exsize);
dirfpos+=6+csize;
fseek( imp,fpos,SEEK_SET );
dirbufend+=i;
return true;
}
void CImpTool::init_getbits()
{
dcsrc=dcend=dcbuffer;
bitpos=0;
bitbuf=0;
}
unsigned long CImpTool::getbits(int nbits)
{
int iseof=0;
if( nbits>bitpos )
while( bitpos<25 )
{
if(dcsrc>=dcend)
{
dcsrc=dcbuffer;
if(!iseof)
{
dcend=dcbuffer+fread(dcbuffer,1,sizeof(dcbuffer),imp);
iseof=feof(imp);
}
}
bitbuf+=(*dcsrc++)<<bitpos;
bitpos+=8;
}
return bitbuf;
}
int CImpTool::unstore(unsigned char *output,int size)
{
fseek(imp,dcsrc-dcend-(bitpos>>3),SEEK_CUR);
return fread(output,1,size,imp);
}
int CImpTool::decomp( FILE *outfile,unsigned long fpos,unsigned long unitpos,unsigned long togo,unsigned char flags)
{
unsigned char lhbuf[LOCAL_HEADER_SIZE];
unsigned short namelen;
int i,lhptr,nameptr;
unsigned long method,level,ovlevel;
int nread,written;
unsigned long overlap,e8offset,srcsize,block_csize;
unsigned char *blocksrc;
if(!togo){g_crc=0;return 0;}
g_crc=0xFFFFFFFF;
g_e8extra=0;
srcsize=togo;
e8offset=0;
g_exlast=0;
lhptr=0;nameptr=0;
g_e8t=0;
if(flags&DFLAG_E8SHORT)g_e8t=2;
else if(flags&DFLAG_E8LONG)g_e8t=4;
fpos+=6+g_exesize;
if(fpos!=g_prevfpos || unitpos<g_unitoffset)
{
g_blockstart=0;
g_blocksize=0;
g_exlast=0;
g_exprev=0;
g_unitoffset=0;
g_exerror=0;
g_mmptr=0;
g_prevfpos=fpos;
fseek(imp,fpos,SEEK_SET);
if(g_blockbuffer){delete [] g_blockbuffer;g_blockbuffer=NULL;}
}
while(togo)
{
if(g_exerror)return -3;
if(unitpos<g_unitoffset+g_blocksize)
{
blocksrc=g_blockbuffer+g_blockstart+unitpos-g_unitoffset;
nread=g_blocksize-(unitpos-g_unitoffset);
if(lhptr<LOCAL_HEADER_SIZE)
{
i=LOCAL_HEADER_SIZE-lhptr;
if(i>nread)i=nread;
memcpy(lhbuf+lhptr,blocksrc,i);
lhptr+=i;
unitpos+=i;
nread-=i;
if(lhptr<LOCAL_HEADER_SIZE)continue;
}
namelen=lhbuf[4]+(lhbuf[5]<<8);
if(nameptr<namelen)
{
i=namelen-nameptr;
if(i>nread)i=nread;
nameptr+=i;
unitpos+=i;
continue;
}
if((unsigned)nread>togo)nread=togo;
if(!g_e8t)
{
g_crc=calc_crc(blocksrc,nread,g_crc);
written=fwrite(blocksrc,1,nread,outfile);
}
else
{
i=e8ut_crc_write(outfile,blocksrc,nread,e8offset,srcsize,(unsigned)nread==togo);
if(i<0)return i;
written=nread;
e8offset+=nread;
}
togo-=nread;
unitpos+=nread;
}
if(togo)
{
g_exerror=1;
if(g_exlast)return 0;
g_blockstart+=g_blocksize;
g_unitoffset+=g_blocksize;
fpos=ftell(imp);
init_getbits();
method=getbits(4)&15;
USEDBITS(4);
if(method>METHOD_LZ77_MM)return -3;
g_exlast=(unsigned char)getbits(1)&1;
USEDBITS(1);
g_blocksize=getbits(20)&((1L<<20)-1);
USEDBITS(20);
block_csize=getbits(20)&((1L<<20)-1);
USEDBITS(20);
if(!g_blockbuffer)
{
g_exmemory=g_blocksize+512;
g_blockbuffer=new unsigned char[g_exmemory];
}
if(method==METHOD_LZ77 || method==METHOD_LZ77_MM)
{
if(g_exprev)
{
level=getbits(2)&3;
USEDBITS(2);
if(level>2)return -3;
ovlevel=getbits(3)&7;
USEDBITS(3);
overlap=g_overlaps[level][ovlevel];
redo_mm(overlap);
if(g_blockstart>overlap)
{
memmove(g_blockbuffer,g_blockbuffer+g_blockstart-overlap,overlap);
g_blockstart=overlap;
}
if(g_blocksize+g_blockstart>g_exmemory)
{
unsigned long old_ex = g_exmemory;
g_exmemory=g_blocksize+g_blockstart+512;
unsigned char *t = new unsigned char[g_exmemory];
memcpy(t,g_blockbuffer,old_ex);
g_blockbuffer=t;
}
}
else USEDBITS(5);
written=expand_lz(g_blockbuffer,g_blockstart,g_blocksize,1);
if(written<0)return written;
if((unsigned long)written<g_blocksize){g_blocksize=(unsigned long)written;g_exlast=1;}
}
else
{
if(g_blocksize>g_exmemory)
{
unsigned long old_ex = g_exmemory;
g_exmemory=g_blocksize+512;
unsigned char *t = new unsigned char[g_exmemory];
memcpy(t,g_blockbuffer,old_ex);
g_blockbuffer=t;
}
if(!g_exlast)
{
overlap=524288-g_blocksize;
if((int)overlap<0)overlap=0;
else if(overlap>g_exmemory-g_blocksize)overlap=g_exmemory-g_blocksize;
redo_mm(overlap);
if(g_blockstart>overlap)
{
memmove(g_blockbuffer,g_blockbuffer+g_blockstart-overlap,overlap);
g_blockstart=overlap;
}
}
else g_blockstart=0;
g_mmptr=0;
if(method==METHOD_BWT)
{
i=expand_bwt(g_blockbuffer+g_blockstart,g_blocksize);
if(i<0)return i;
}
else
{
i=unstore(g_blockbuffer+g_blockstart,g_blocksize);
if(i<0)return i;
if((unsigned long)i<g_blocksize){g_blocksize=(unsigned long)i;g_exlast=1;}
}
}
fseek(imp,fpos+block_csize,SEEK_SET);
g_exerror=0;
g_exprev=1;
}
}
g_crc=~g_crc;
return 0;
}
int CImpTool::expand_bwt(unsigned char *output, int exsize)
{
int count[257];
unsigned char hclengths[BWTABLES][NCODES];
unsigned long huffcodes[NCODES];
int ttable[BWTABLES][BWTTSIZE];
int hdchain[BWTABLES][NCODES][2];
unsigned char mtf[256],treemtf[BWTABLES];
unsigned long *links;
unsigned char *dest,*output_end;
int i,treenum,code,codes,numtrees;
int rptbase,rpt,link,start;
unsigned long hcode;
unsigned char rc;
rc=(unsigned char)getbits(8)&0xFF;
USEDBITS(8);
numtrees=getbits(3)&7;
USEDBITS(3);
if(numtrees<1)return -3;
for(treenum=0;treenum<numtrees;treenum++)
{
i=load_hcodes(hclengths[treenum],NCODES,1,0);
if(i<0)return i;
make_codes(huffcodes,hclengths[treenum],NCODES);
make_decode_tables(ttable[treenum],hdchain[treenum],huffcodes,hclengths[treenum],BWTTBITS,NCODES);
}
bitpos&=~7;
for(i=0;i<256;i++)mtf[i]=i;
for(i=0;i<BWTABLES;i++)treemtf[i]=i;
memset(count,0,sizeof(count));
rptbase=1;codes=WINDOW;
dest=output;
output_end=output+exsize+1;
start=0; /*prevent crash from invalid data*/
while(dest<output_end)
{
if(codes==WINDOW)
{
hcode=getbits(numtrees);
code=0;
while(hcode&1){hcode>>=1;code++;}
if(code>=numtrees)return -3;
USEDBITS(code+1);
treenum=treemtf[code];
if(code)
{
for(;code;code--)treemtf[code]=treemtf[code-1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -