370 lines
9.6 KiB
C++
370 lines
9.6 KiB
C++
#include "rar.hpp"
|
|
#include "dll.hpp"
|
|
|
|
static int RarErrorToDll(int ErrCode);
|
|
|
|
struct DataSet
|
|
{
|
|
CommandData Cmd;
|
|
CmdExtract Extract;
|
|
Archive Arc;
|
|
int OpenMode;
|
|
int HeaderSize;
|
|
|
|
DataSet():Arc(&Cmd) {};
|
|
};
|
|
|
|
|
|
HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r)
|
|
{
|
|
RAROpenArchiveDataEx rx;
|
|
memset(&rx,0,sizeof(rx));
|
|
rx.ArcName=r->ArcName;
|
|
rx.OpenMode=r->OpenMode;
|
|
rx.CmtBuf=r->CmtBuf;
|
|
rx.CmtBufSize=r->CmtBufSize;
|
|
HANDLE hArc=RAROpenArchiveEx(&rx);
|
|
r->OpenResult=rx.OpenResult;
|
|
r->CmtSize=rx.CmtSize;
|
|
r->CmtState=rx.CmtState;
|
|
return(hArc);
|
|
}
|
|
|
|
|
|
HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
|
|
{
|
|
try
|
|
{
|
|
r->OpenResult=0;
|
|
DataSet *Data=new DataSet;
|
|
Data->Cmd.DllError=0;
|
|
Data->OpenMode=r->OpenMode;
|
|
Data->Cmd.FileArgs->AddString("*");
|
|
|
|
char an[NM];
|
|
if (r->ArcName==NULL && r->ArcNameW!=NULL)
|
|
{
|
|
WideToChar(r->ArcNameW,an,NM);
|
|
r->ArcName=an;
|
|
}
|
|
|
|
Data->Cmd.AddArcName(r->ArcName,r->ArcNameW);
|
|
Data->Cmd.Overwrite=OVERWRITE_ALL;
|
|
Data->Cmd.VersionControl=1;
|
|
if (!Data->Arc.Open(r->ArcName,r->ArcNameW))
|
|
{
|
|
r->OpenResult=ERAR_EOPEN;
|
|
delete Data;
|
|
return(NULL);
|
|
}
|
|
if (!Data->Arc.IsArchive(false))
|
|
{
|
|
r->OpenResult=Data->Cmd.DllError!=0 ? Data->Cmd.DllError:ERAR_BAD_ARCHIVE;
|
|
delete Data;
|
|
return(NULL);
|
|
}
|
|
r->Flags=Data->Arc.NewMhd.Flags;
|
|
Array<byte> CmtData;
|
|
if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtData,NULL))
|
|
{
|
|
r->Flags|=2;
|
|
size_t Size=CmtData.Size()+1;
|
|
r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
|
|
r->CmtSize=(uint)Min(Size,r->CmtBufSize);
|
|
memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
|
|
if (Size<=r->CmtBufSize)
|
|
r->CmtBuf[r->CmtSize-1]=0;
|
|
}
|
|
else
|
|
r->CmtState=r->CmtSize=0;
|
|
if (Data->Arc.Signed)
|
|
r->Flags|=0x20;
|
|
Data->Extract.ExtractArchiveInit(&Data->Cmd,Data->Arc);
|
|
return((HANDLE)Data);
|
|
}
|
|
catch (int ErrCode)
|
|
{
|
|
r->OpenResult=RarErrorToDll(ErrCode);
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
|
|
int PASCAL RARCloseArchive(HANDLE hArcData)
|
|
{
|
|
DataSet *Data=(DataSet *)hArcData;
|
|
bool Success=Data==NULL ? false:Data->Arc.Close();
|
|
delete Data;
|
|
return(Success ? 0:ERAR_ECLOSE);
|
|
}
|
|
|
|
|
|
int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
|
|
{
|
|
DataSet *Data=(DataSet *)hArcData;
|
|
try
|
|
{
|
|
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(FILE_HEAD))<=0)
|
|
{
|
|
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==ENDARC_HEAD &&
|
|
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
|
|
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
|
{
|
|
Data->Extract.SignatureFound=false;
|
|
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
|
return(RARReadHeader(hArcData,D));
|
|
}
|
|
else
|
|
return(ERAR_EOPEN);
|
|
return(Data->Arc.BrokenFileHeader ? ERAR_BAD_DATA:ERAR_END_ARCHIVE);
|
|
}
|
|
if (Data->OpenMode==RAR_OM_LIST && (Data->Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
|
|
{
|
|
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
|
|
if (Code==0)
|
|
return(RARReadHeader(hArcData,D));
|
|
else
|
|
return(Code);
|
|
}
|
|
strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
|
|
strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(D->FileName));
|
|
D->Flags=Data->Arc.NewLhd.Flags;
|
|
D->PackSize=Data->Arc.NewLhd.PackSize;
|
|
D->UnpSize=Data->Arc.NewLhd.UnpSize;
|
|
D->HostOS=Data->Arc.NewLhd.HostOS;
|
|
D->FileCRC=Data->Arc.NewLhd.FileCRC;
|
|
D->FileTime=Data->Arc.NewLhd.FileTime;
|
|
D->UnpVer=Data->Arc.NewLhd.UnpVer;
|
|
D->Method=Data->Arc.NewLhd.Method;
|
|
D->FileAttr=Data->Arc.NewLhd.FileAttr;
|
|
D->CmtSize=0;
|
|
D->CmtState=0;
|
|
}
|
|
catch (int ErrCode)
|
|
{
|
|
return(RarErrorToDll(ErrCode));
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
|
|
{
|
|
DataSet *Data=(DataSet *)hArcData;
|
|
try
|
|
{
|
|
if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(FILE_HEAD))<=0)
|
|
{
|
|
if (Data->Arc.Volume && Data->Arc.GetHeaderType()==ENDARC_HEAD &&
|
|
(Data->Arc.EndArcHead.Flags & EARC_NEXT_VOLUME))
|
|
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
|
{
|
|
Data->Extract.SignatureFound=false;
|
|
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
|
return(RARReadHeaderEx(hArcData,D));
|
|
}
|
|
else
|
|
return(ERAR_EOPEN);
|
|
return(Data->Arc.BrokenFileHeader ? ERAR_BAD_DATA:ERAR_END_ARCHIVE);
|
|
}
|
|
if (Data->OpenMode==RAR_OM_LIST && (Data->Arc.NewLhd.Flags & LHD_SPLIT_BEFORE))
|
|
{
|
|
int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
|
|
if (Code==0)
|
|
return(RARReadHeaderEx(hArcData,D));
|
|
else
|
|
return(Code);
|
|
}
|
|
strncpyz(D->ArcName,Data->Arc.FileName,ASIZE(D->ArcName));
|
|
if (*Data->Arc.FileNameW)
|
|
strncpyw(D->ArcNameW,Data->Arc.FileNameW,sizeof(D->ArcNameW));
|
|
else
|
|
CharToWide(Data->Arc.FileName,D->ArcNameW);
|
|
strncpyz(D->FileName,Data->Arc.NewLhd.FileName,ASIZE(D->FileName));
|
|
if (*Data->Arc.NewLhd.FileNameW)
|
|
strncpyw(D->FileNameW,Data->Arc.NewLhd.FileNameW,sizeof(D->FileNameW));
|
|
else
|
|
{
|
|
#ifdef _WIN_32
|
|
char AnsiName[NM];
|
|
OemToChar(Data->Arc.NewLhd.FileName,AnsiName);
|
|
CharToWide(AnsiName,D->FileNameW);
|
|
#else
|
|
CharToWide(Data->Arc.NewLhd.FileName,D->FileNameW);
|
|
#endif
|
|
}
|
|
D->Flags=Data->Arc.NewLhd.Flags;
|
|
D->PackSize=Data->Arc.NewLhd.PackSize;
|
|
D->PackSizeHigh=Data->Arc.NewLhd.HighPackSize;
|
|
D->UnpSize=Data->Arc.NewLhd.UnpSize;
|
|
D->UnpSizeHigh=Data->Arc.NewLhd.HighUnpSize;
|
|
D->HostOS=Data->Arc.NewLhd.HostOS;
|
|
D->FileCRC=Data->Arc.NewLhd.FileCRC;
|
|
D->FileTime=Data->Arc.NewLhd.FileTime;
|
|
D->UnpVer=Data->Arc.NewLhd.UnpVer;
|
|
D->Method=Data->Arc.NewLhd.Method;
|
|
D->FileAttr=Data->Arc.NewLhd.FileAttr;
|
|
D->CmtSize=0;
|
|
D->CmtState=0;
|
|
}
|
|
catch (int ErrCode)
|
|
{
|
|
return(RarErrorToDll(ErrCode));
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName,wchar *DestPathW,wchar *DestNameW)
|
|
{
|
|
DataSet *Data=(DataSet *)hArcData;
|
|
try
|
|
{
|
|
Data->Cmd.DllError=0;
|
|
if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
|
|
Operation==RAR_SKIP && !Data->Arc.Solid)
|
|
{
|
|
if (Data->Arc.Volume &&
|
|
Data->Arc.GetHeaderType()==FILE_HEAD &&
|
|
(Data->Arc.NewLhd.Flags & LHD_SPLIT_AFTER)!=0)
|
|
if (MergeArchive(Data->Arc,NULL,false,'L'))
|
|
{
|
|
Data->Extract.SignatureFound=false;
|
|
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
|
return(0);
|
|
}
|
|
else
|
|
return(ERAR_EOPEN);
|
|
Data->Arc.SeekToNext();
|
|
}
|
|
else
|
|
{
|
|
Data->Cmd.DllOpMode=Operation;
|
|
|
|
if (DestPath!=NULL || DestName!=NULL)
|
|
{
|
|
#ifdef _WIN_32
|
|
OemToChar(NullToEmpty(DestPath),Data->Cmd.ExtrPath);
|
|
#else
|
|
strcpy(Data->Cmd.ExtrPath,NullToEmpty(DestPath));
|
|
#endif
|
|
AddEndSlash(Data->Cmd.ExtrPath);
|
|
#ifdef _WIN_32
|
|
OemToChar(NullToEmpty(DestName),Data->Cmd.DllDestName);
|
|
#else
|
|
strcpy(Data->Cmd.DllDestName,NullToEmpty(DestName));
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
*Data->Cmd.ExtrPath=0;
|
|
*Data->Cmd.DllDestName=0;
|
|
}
|
|
|
|
if (DestPathW!=NULL || DestNameW!=NULL)
|
|
{
|
|
strncpyw(Data->Cmd.ExtrPathW,NullToEmpty(DestPathW),NM-2);
|
|
AddEndSlash(Data->Cmd.ExtrPathW);
|
|
strncpyw(Data->Cmd.DllDestNameW,NullToEmpty(DestNameW),NM-1);
|
|
|
|
if (*Data->Cmd.DllDestNameW!=0 && *Data->Cmd.DllDestName==0)
|
|
WideToChar(Data->Cmd.DllDestNameW,Data->Cmd.DllDestName);
|
|
}
|
|
else
|
|
{
|
|
*Data->Cmd.ExtrPathW=0;
|
|
*Data->Cmd.DllDestNameW=0;
|
|
}
|
|
|
|
strcpy(Data->Cmd.Command,Operation==RAR_EXTRACT ? "X":"T");
|
|
Data->Cmd.Test=Operation!=RAR_EXTRACT;
|
|
bool Repeat=false;
|
|
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
|
|
|
|
while (Data->Arc.ReadHeader()!=0 && Data->Arc.GetHeaderType()==NEWSUB_HEAD)
|
|
{
|
|
Data->Extract.ExtractCurrentFile(&Data->Cmd,Data->Arc,Data->HeaderSize,Repeat);
|
|
Data->Arc.SeekToNext();
|
|
}
|
|
Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
|
|
}
|
|
}
|
|
catch (int ErrCode)
|
|
{
|
|
return(RarErrorToDll(ErrCode));
|
|
}
|
|
return(Data->Cmd.DllError);
|
|
}
|
|
|
|
|
|
int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
|
|
{
|
|
return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL));
|
|
}
|
|
|
|
|
|
int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName)
|
|
{
|
|
return(ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName));
|
|
}
|
|
|
|
|
|
void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
|
|
{
|
|
DataSet *Data=(DataSet *)hArcData;
|
|
Data->Cmd.ChangeVolProc=ChangeVolProc;
|
|
}
|
|
|
|
|
|
void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData)
|
|
{
|
|
DataSet *Data=(DataSet *)hArcData;
|
|
Data->Cmd.Callback=Callback;
|
|
Data->Cmd.UserData=UserData;
|
|
}
|
|
|
|
|
|
void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc)
|
|
{
|
|
DataSet *Data=(DataSet *)hArcData;
|
|
Data->Cmd.ProcessDataProc=ProcessDataProc;
|
|
}
|
|
|
|
#ifndef NOCRYPT
|
|
void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
|
|
{
|
|
DataSet *Data=(DataSet *)hArcData;
|
|
strncpyz(Data->Cmd.Password,Password,ASIZE(Data->Cmd.Password));
|
|
}
|
|
#endif
|
|
|
|
|
|
int PASCAL RARGetDllVersion()
|
|
{
|
|
return(RAR_DLL_VERSION);
|
|
}
|
|
|
|
|
|
static int RarErrorToDll(int ErrCode)
|
|
{
|
|
switch(ErrCode)
|
|
{
|
|
case FATAL_ERROR:
|
|
return(ERAR_EREAD);
|
|
case CRC_ERROR:
|
|
return(ERAR_BAD_DATA);
|
|
case WRITE_ERROR:
|
|
return(ERAR_EWRITE);
|
|
case OPEN_ERROR:
|
|
return(ERAR_EOPEN);
|
|
case CREATE_ERROR:
|
|
return(ERAR_ECREATE);
|
|
case MEMORY_ERROR:
|
|
return(ERAR_NO_MEMORY);
|
|
case SUCCESS:
|
|
return(0);
|
|
default:
|
|
return(ERAR_UNKNOWN);
|
|
}
|
|
}
|