QuietUnrar/libunrar/dll.cpp

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);
}
}