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

📄 rartool.cpp

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

#include "stdafx.h"
#include "RarTool.h"

bool CRarTool::Check( const char* fname, unsigned long fsize )
{
	if( (arc=fopen(fname,"rb"))==NULL )
		return false;
	bool ans=IsArchive(true);
	fclose(arc);
	return ans;
}

bool CRarTool::Extract( const char* fname,const char* ddir )
{
	// 曄悢弶婜壔
	bool bFirstVol=true,bFirstFile=true;
	char *DestName;
	bNeedNextVol=false;
	char PassWord[128]={0};
	TCHAR t_DestName[MAX_PATH]; // by uema2.
	strcpy(ArcName,fname);

	// 奐偔
	arc=fopen(fname,"rb");
	if( arc==NULL )return false;
	if( !IsArchive(false) ){fclose(arc);return false;}
	fseek(arc,NewMhd.HeadSize-MainHeadSize,SEEK_CUR);
	
	while( true )
    {
		int Size=ReadBlock(FILE_HEAD|READSUBBLOCK);
		if( Size<=0 && !bNeedNextVol )		break;
		if( BlockHead.HeadType==SUB_HEAD )
		{fseek(arc,NextBlockPos,SEEK_SET);continue;}

		// 儅儖僠儃儕儏乕儉張棟
		if( (NewLhd.Flags&LHD_SPLIT_BEFORE) && bSolid && bFirstVol )break;
		bFirstVol=false;
		if( bNeedNextVol && Size==0 && !GetNextVolume() )break;
		bNeedNextVol=(0!=(NewLhd.Flags&LHD_SPLIT_AFTER));

		// 埑弅僨乕僞埵抲傊旘傇
		fseek(arc,NextBlockPos-NewLhd.PackSize,SEEK_SET);

		if( !(NewLhd.Flags&LHD_SPLIT_BEFORE) )
		{
			// 僷僗儚乕僪擖椡
			if( NewLhd.Flags&LHD_PASSWORD )
				if( *PassWord==0 )
					strncpy(PassWord,GetPassword(),sizeof(PassWord));

			// 奿擺偝傟偰傞偺偑僼傽僀儖偩偭偨傜側傫偐張棟丅
			if( NewLhd.FileAttr&0x08 )	continue;
			if( NewLhd.HostOS==UNIX ){NewLhd.FileAttr=(NewLhd.FileAttr&0x40)?0x10:0x20;}

			//by uema2.
			DestName = (char*)LocalAlloc(LPTR, MAX_PATH*sizeof(char)); // by uema2.
			sprintf(DestName, "%s\\%s", ueutil::GetExtractPath(), kiutil::pathMake( ExtrName ));

//			DestName = kiutil::pathMake( ExtrName );
			if( NewLhd.FileAttr&0x10 )	continue;

			// 揥奐
			out=fopen( DestName,"wb" );
			if( out!=NULL )
			{
				CurUnpRead=CurUnpWrite=0;
				UnpFileCRC=(ArcFormat==OLD)?0:0xFFFFFFFFL;
				PackedCRC=0xFFFFFFFFL;

				if( 0!=(Encryption=((*PassWord!=0)&&(NewLhd.Flags&LHD_PASSWORD))?NewLhd.UnpVer:0) )
					SetCryptKeys(PassWord);

				UnpPackedSize=NewLhd.PackSize;
				DestUnpSize=NewLhd.UnpSize;

				if( NewLhd.Method==0x30 )
					Unstore();
				else if( NewLhd.UnpVer<13 || NewLhd.UnpVer>UNP_VER );
				else if( NewLhd.UnpVer<=15 )
					OldUnpack(!bFirstFile&&bSolid);
				else
				    Unpack(0!=(NewLhd.Flags&LHD_SOLID));

				fclose(out);

				//DestName傪TCHAR偵 by uema2.
				_MultiByteToWideChar(CP_ACP, 0, DestName, strlen(DestName)+1,
					t_DestName, strlen(DestName)+1);

				if( !(ArcFormat==OLD && UnpFileCRC==NewLhd.FileCRC) && !(ArcFormat==NEW && UnpFileCRC==~NewLhd.FileCRC) )
				{
					if( NewLhd.Flags&LHD_PASSWORD )	// Bad CRC
//						DeleteFile(DestName);
						DeleteFile(t_DestName); //by uema2.
				}
				else
				{
					kiutil::timeSet(DestName,(WORD)(NewLhd.FileTime>>16),(WORD)NewLhd.FileTime);
//					SetFileAttributes(DestName,NewLhd.FileAttr);
					SetFileAttributes(t_DestName,NewLhd.FileAttr); //fixed by uema2.
				}
			}
			LocalFree(DestName); // by uema2.
		}

		if(arc==NULL)break;
		bFirstFile=false;
		fseek(arc,NextBlockPos,SEEK_SET);
    }

	fclose(arc);
	return true;
}

/**** Unpackers(Old) *****************************************************/
#define GetBits()                                                 \
        BitField = ( ( ( (DWORD)InBuf[InAddr]   << 16 ) |        \
                       ( (WORD) InBuf[InAddr+1] <<  8 ) |        \
                       (         InBuf[InAddr+2]       ) )        \
                       >> (8-InBit) ) & 0xffff;
#define AddBits(Bits)                          \
        InAddr += ( InBit + (Bits) ) >> 3;     \
        InBit  =  ( InBit + (Bits) ) &  7;

static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,
                                 0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0};
static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,
                                 0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
#define STARTL1  2
static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
                             0xee00,0xf000,0xf200,0xf200,0xffff};
static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32};
#define STARTL2  3
static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00,
                             0xf000,0xf200,0xf240,0xffff};
static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36};
#define STARTHF0  4
static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200,
                              0xf200,0xf200,0xffff};
static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33};
#define STARTHF1  5
static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200,
                              0xf7e0,0xffff};
static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127};
#define STARTHF2  5
static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff,
                              0xffff,0xffff};
static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0};
#define STARTHF3  6
static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff,
                              0xffff};
static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0};
#define STARTHF4  8
static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff};
static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0};


void CRarTool::OldUnpack(bool bSolid)
{
  int SetStMode=0;
  UnpInitData(bSolid);
  OldUnpInitData(bSolid);
  UnpReadBuf(1);
  if (!bSolid)
  {
    InitHuff();
    UnpPtr=0;
  }
  else
    UnpPtr=WrPtr;
  DestUnpSize--;

  if (SetStMode)
    StMode=1;
  else
    if (DestUnpSize>=0)
    {
      GetFlagsBuf();
      FlagsCnt=8;
    }

  while (DestUnpSize>=0)
  {
    UnpPtr&=MAXWINMASK;

    if (InAddr>sizeof(InBuf)-30)
      UnpReadBuf(0);
    if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
    {
      UnpWriteBuf();
    }
    if (StMode)
    {
      HuffDecode();
      continue;
    }

    if (--FlagsCnt < 0)
    {
      GetFlagsBuf();
      FlagsCnt=7;
    }

    if (FlagBuf & 0x80)
    {
      FlagBuf<<=1;
      if (Nlzb > Nhfb)
        LongLZ();
      else
        HuffDecode();
    }
    else
    {
      FlagBuf<<=1;
      if (--FlagsCnt < 0)
      {
        GetFlagsBuf();
        FlagsCnt=7;
      }
      if (FlagBuf & 0x80)
      {
        FlagBuf<<=1;
        if (Nlzb > Nhfb)
          HuffDecode();
        else
          LongLZ();
      }
      else
      {
        FlagBuf<<=1;
        ShortLZ();
      }
    }
  }
  UnpWriteBuf();
}


void CRarTool::ShortLZ()
{
  unsigned int Length,SaveLength;
  unsigned int LastDistance;
  unsigned int Distance;
  int DistancePlace;
  NumHuf=0;
  GetBits();
  if (LCount==2)
  {
    AddBits(1);
    if (BitField >= 0x8000)
    {
      OldCopyString((unsigned int)LastDist,LastLength);
      return;
    }
    BitField <<= 1;
    LCount=0;
  }

  BitField>>=8;

  ShortLen1[1]=ShortLen2[3]=Buf60+3;

  if (AvrLn1<37)
  {
    for (Length=0;;Length++)
      if (((BitField^ShortXor1[Length]) & (~(0xff>>ShortLen1[Length])))==0)
        break;
    AddBits(ShortLen1[Length]);
  }
  else
  {
    for (Length=0;;Length++)
      if (((BitField^ShortXor2[Length]) & (~(0xff>>ShortLen2[Length])))==0)
        break;
    AddBits(ShortLen2[Length]);
  }

  if (Length >= 9)
  {
    if (Length == 9)
    {
      LCount++;
      OldCopyString((unsigned int)LastDist,LastLength);
      return;
    }
    if (Length == 14)
    {
      LCount=0;
      GetBits();
      Length=DecodeNum(BitField,STARTL2,DecL2,PosL2)+5;
      GetBits();
      Distance=(BitField>>1) | 0x8000;
      AddBits(15);
      LastLength=Length;
      LastDist=Distance;
      OldCopyString(Distance,Length);
      return;
    }

    LCount=0;
    SaveLength=Length;
    Distance=OldDist[(OldDistPtr-(Length-9)) & 3];
    GetBits();
    Length=DecodeNum(BitField,STARTL1,DecL1,PosL1)+2;
    if (Length==0x101 && SaveLength==10)
    {
      Buf60 ^= 1;
      return;
    }
    if (Distance > 256)
      Length++;
    if (Distance >= MaxDist3)
      Length++;

    OldDist[OldDistPtr++]=Distance;
    OldDistPtr = OldDistPtr & 3;
    LastLength=Length;
    LastDist=Distance;
    OldCopyString(Distance,Length);
    return;
  }

  LCount=0;
  AvrLn1 += Length;
  AvrLn1 -= AvrLn1 >> 4;

  GetBits();
  DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
  Distance=ChSetA[DistancePlace];
  if (--DistancePlace != -1)
  {
    PlaceA[Distance]--;
    LastDistance=ChSetA[DistancePlace];
    PlaceA[LastDistance]++;
    ChSetA[DistancePlace+1]=LastDistance;
    ChSetA[DistancePlace]=Distance;
  }
  Length+=2;
  OldDist[OldDistPtr++] = ++Distance;
  OldDistPtr = OldDistPtr & 3;
  LastLength=Length;
  LastDist=Distance;
  OldCopyString(Distance,Length);
  return;
}


void CRarTool::LongLZ()
{
  unsigned int Length;
  unsigned int Distance;
  unsigned int DistancePlace,NewDistancePlace;
  unsigned int OldAvr2,OldAvr3;

  NumHuf=0;
  Nlzb+=16;
  if (Nlzb > 0xff)
  {
    Nlzb=0x90;
    Nhfb >>= 1;
  }
  OldAvr2=AvrLn2;

  GetBits();
  if (AvrLn2 >= 122)
    Length=DecodeNum(BitField,STARTL2,DecL2,PosL2);
  else
    if (AvrLn2 >= 64)
      Length=DecodeNum(BitField,STARTL1,DecL1,PosL1);
    else
      if (BitField < 0x100)
      {
        Length=BitField;
        AddBits(16);
      }
      else
      {
        for (Length=0;((BitField<<Length)&0x8000)==0;Length++)
          ;
        AddBits(Length+1);
      }

  AvrLn2 += Length;
  AvrLn2 -= AvrLn2 >> 5;

  GetBits();
  if (AvrPlcB > 0x28ff)
    DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
  else
    if (AvrPlcB > 0x6ff)
      DistancePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
    else
      DistancePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);

  AvrPlcB += DistancePlace;
  AvrPlcB -= AvrPlcB >> 8;
  while (1)
  {
    Distance = ChSetB[DistancePlace];
    NewDistancePlace = NToPlB[Distance++ & 0xff]++;
    if (!(Distance & 0xff))
      CorrHuff(ChSetB,NToPlB);
    else
      break;
  }

  ChSetB[DistancePlace]=ChSetB[NewDistancePlace];
  ChSetB[NewDistancePlace]=Distance;

  GetBits();
  Distance=((WORD)((Distance & 0xff00) | (BitField >> 8))) >> 1;
  AddBits(7);

  OldAvr3=AvrLn3;
  if (Length!=1 && Length!=4)
    if (Length==0 && Distance <= MaxDist3)
    {
      AvrLn3++;
      AvrLn3 -= AvrLn3 >> 8;
    }
    else
      if (AvrLn3 > 0)
        AvrLn3--;
  Length+=3;
  if (Distance >= MaxDist3)
    Length++;
  if (Distance <= 256)
    Length+=8;
  if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40)
    MaxDist3=0x7f00;
  else
    MaxDist3=0x2001;
  OldDist[OldDistPtr++]=Distance;
  OldDistPtr = OldDistPtr & 3;
  LastLength=Length;
  LastDist=Distance;
  OldCopyString(Distance,Length);
}


void CRarTool::HuffDecode()
{
  unsigned int CurByte,NewBytePlace;
  unsigned int Length;
  unsigned int Distance;
  int BytePlace;

  GetBits();

  if (AvrPlc > 0x75ff)
    BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4);
  else
    if (AvrPlc > 0x5dff)
      BytePlace=DecodeNum(BitField,STARTHF3,DecHf3,PosHf3);
    else
      if (AvrPlc > 0x35ff)
        BytePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
      else
        if (AvrPlc > 0x0dff)
          BytePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
        else
          BytePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
  if (StMode)
  {
    if (BytePlace==0 && BitField > 0xfff)
      BytePlace=0x100;
    if (--BytePlace==-1)
    {
      GetBits();
      AddBits(1);
      if (BitField & 0x8000)
      {
        NumHuf=StMode=0;
        return;
      }
      else
      {
        Length = (BitField & 0x4000) ? 4 : 3;
        AddBits(1);
        GetBits();
        Distance=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
        GetBits();
        Distance = (Distance << 5) | (BitField >> 11);
        AddBits(5);
        OldCopyString(Distance,Length);
        return;
      }
    }
  }
  else
    if (NumHuf++ >= 16 && FlagsCnt==0)
      StMode=1;
  AvrPlc += BytePlace;
  AvrPlc -= AvrPlc >> 8;
  Nhfb+=16;
  if (Nhfb > 0xff)
  {
    Nhfb=0x90;
    Nlzb >>= 1;
  }

  CTool::common_buf[UnpPtr++]=(BYTE)(ChSet[BytePlace]>>8);
  DestUnpSize--;

  while (1)
  {
    CurByte=ChSet[BytePlace];
    NewBytePlace=NToPl[CurByte++ & 0xff]++;
    if ((CurByte & 0xff) > 0xa1)
      CorrHuff(ChSet,NToPl);
    else
      break;
  }

  ChSet[BytePlace]=ChSet[NewBytePlace];
  ChSet[NewBytePlace]=CurByte;
}


void CRarTool::GetFlagsBuf()
{
  unsigned int Flags,FlagsPlace,NewFlagsPlace;

  GetBits();
  FlagsPlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);

  while (1)
  {
    Flags=ChSetC[FlagsPlace];
    FlagBuf=Flags>>8;
    NewFlagsPlace=NToPlC[Flags++ & 0xff]++;
    if ((Flags & 0xff) == 0)
      CorrHuff(ChSetC,NToPlC);
    else
      break;
  }

  ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace];
  ChSetC[NewFlagsPlace]=Flags;
}

void CRarTool::OldUnpInitData(bool bSolid)
{
  if(!bSolid)
  {
    AvrPlcB=AvrLn1=AvrLn2=AvrLn3=NumHuf=Buf60=0;
    AvrPlc=0x3500;
    MaxDist3=0x2001;
    Nhfb=Nlzb=0x80;
  }
  FlagsCnt=0;
  FlagBuf=0;
  StMode=0;
  LCount=0;
}

⌨️ 快捷键说明

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