"Fossies" - the Fresh Open Source Software Archive

Member "unrar/dll.cpp" (4 May 2022, 13506 Bytes) of package /linux/misc/unrarsrc-6.1.7.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dll.cpp" see the Fossies "Dox" file reference documentation.

    1 #include "rar.hpp"
    2 
    3 static int RarErrorToDll(RAR_EXIT ErrCode);
    4 
    5 struct DataSet
    6 {
    7   CommandData Cmd;
    8   Archive Arc;
    9   CmdExtract Extract;
   10   int OpenMode;
   11   int HeaderSize;
   12 
   13   DataSet():Arc(&Cmd),Extract(&Cmd) {};
   14 };
   15 
   16 
   17 HANDLE PASCAL RAROpenArchive(struct RAROpenArchiveData *r)
   18 {
   19   RAROpenArchiveDataEx rx;
   20   memset(&rx,0,sizeof(rx));
   21   rx.ArcName=r->ArcName;
   22   rx.OpenMode=r->OpenMode;
   23   rx.CmtBuf=r->CmtBuf;
   24   rx.CmtBufSize=r->CmtBufSize;
   25   HANDLE hArc=RAROpenArchiveEx(&rx);
   26   r->OpenResult=rx.OpenResult;
   27   r->CmtSize=rx.CmtSize;
   28   r->CmtState=rx.CmtState;
   29   return hArc;
   30 }
   31 
   32 
   33 HANDLE PASCAL RAROpenArchiveEx(struct RAROpenArchiveDataEx *r)
   34 {
   35   DataSet *Data=NULL;
   36   try
   37   {
   38     ErrHandler.Clean();
   39 
   40     r->OpenResult=0;
   41     Data=new DataSet;
   42     Data->Cmd.DllError=0;
   43     Data->OpenMode=r->OpenMode;
   44     Data->Cmd.FileArgs.AddString(L"*");
   45     Data->Cmd.KeepBroken=(r->OpFlags&ROADOF_KEEPBROKEN)!=0;
   46 
   47     char AnsiArcName[NM];
   48     *AnsiArcName=0;
   49     if (r->ArcName!=NULL)
   50     {
   51       strncpyz(AnsiArcName,r->ArcName,ASIZE(AnsiArcName));
   52 #ifdef _WIN_ALL
   53       if (!AreFileApisANSI())
   54       {
   55         OemToCharBuffA(r->ArcName,AnsiArcName,ASIZE(AnsiArcName));
   56         AnsiArcName[ASIZE(AnsiArcName)-1]=0;
   57       }
   58 #endif
   59     }
   60 
   61     wchar ArcName[NM];
   62     GetWideName(AnsiArcName,r->ArcNameW,ArcName,ASIZE(ArcName));
   63 
   64     Data->Cmd.AddArcName(ArcName);
   65     Data->Cmd.Overwrite=OVERWRITE_ALL;
   66     Data->Cmd.VersionControl=1;
   67 
   68     Data->Cmd.Callback=r->Callback;
   69     Data->Cmd.UserData=r->UserData;
   70 
   71     // Open shared mode is added by request of dll users, who need to
   72     // browse and unpack archives while downloading.
   73     Data->Cmd.OpenShared = true;
   74     if (!Data->Arc.Open(ArcName,FMF_OPENSHARED))
   75     {
   76       r->OpenResult=ERAR_EOPEN;
   77       delete Data;
   78       return NULL;
   79     }
   80     if (!Data->Arc.IsArchive(true))
   81     {
   82       if (Data->Cmd.DllError!=0)
   83         r->OpenResult=Data->Cmd.DllError;
   84       else
   85       {
   86         RAR_EXIT ErrCode=ErrHandler.GetErrorCode();
   87         if (ErrCode!=RARX_SUCCESS && ErrCode!=RARX_WARNING)
   88           r->OpenResult=RarErrorToDll(ErrCode);
   89         else
   90           r->OpenResult=ERAR_BAD_ARCHIVE;
   91       }
   92       delete Data;
   93       return NULL;
   94     }
   95     r->Flags=0;
   96     
   97     if (Data->Arc.Volume)
   98       r->Flags|=ROADF_VOLUME;
   99     if (Data->Arc.MainComment)
  100       r->Flags|=ROADF_COMMENT;
  101     if (Data->Arc.Locked)
  102       r->Flags|=ROADF_LOCK;
  103     if (Data->Arc.Solid)
  104       r->Flags|=ROADF_SOLID;
  105     if (Data->Arc.NewNumbering)
  106       r->Flags|=ROADF_NEWNUMBERING;
  107     if (Data->Arc.Signed)
  108       r->Flags|=ROADF_SIGNED;
  109     if (Data->Arc.Protected)
  110       r->Flags|=ROADF_RECOVERY;
  111     if (Data->Arc.Encrypted)
  112       r->Flags|=ROADF_ENCHEADERS;
  113     if (Data->Arc.FirstVolume)
  114       r->Flags|=ROADF_FIRSTVOLUME;
  115 
  116     Array<wchar> CmtDataW;
  117     if (r->CmtBufSize!=0 && Data->Arc.GetComment(&CmtDataW))
  118     {
  119       if (r->CmtBufW!=NULL)
  120       {
  121         CmtDataW.Push(0);
  122         size_t Size=wcslen(&CmtDataW[0])+1;
  123 
  124         r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
  125         r->CmtSize=(uint)Min(Size,r->CmtBufSize);
  126         memcpy(r->CmtBufW,&CmtDataW[0],(r->CmtSize-1)*sizeof(*r->CmtBufW));
  127         r->CmtBufW[r->CmtSize-1]=0;
  128       }
  129       else
  130         if (r->CmtBuf!=NULL)
  131         {
  132           Array<char> CmtData(CmtDataW.Size()*4+1);
  133           memset(&CmtData[0],0,CmtData.Size());
  134           WideToChar(&CmtDataW[0],&CmtData[0],CmtData.Size()-1);
  135           size_t Size=strlen(&CmtData[0])+1;
  136 
  137           r->CmtState=Size>r->CmtBufSize ? ERAR_SMALL_BUF:1;
  138           r->CmtSize=(uint)Min(Size,r->CmtBufSize);
  139           memcpy(r->CmtBuf,&CmtData[0],r->CmtSize-1);
  140           r->CmtBuf[r->CmtSize-1]=0;
  141         }
  142     }
  143     else
  144       r->CmtState=r->CmtSize=0;
  145     Data->Extract.ExtractArchiveInit(Data->Arc);
  146     return (HANDLE)Data;
  147   }
  148   catch (RAR_EXIT ErrCode)
  149   {
  150     if (Data!=NULL && Data->Cmd.DllError!=0)
  151       r->OpenResult=Data->Cmd.DllError;
  152     else
  153       r->OpenResult=RarErrorToDll(ErrCode);
  154     if (Data != NULL)
  155       delete Data;
  156     return NULL;
  157   }
  158   catch (std::bad_alloc&) // Catch 'new' exception.
  159   {
  160     r->OpenResult=ERAR_NO_MEMORY;
  161     if (Data != NULL)
  162       delete Data;
  163   }
  164   return NULL; // To make compilers happy.
  165 }
  166 
  167 
  168 int PASCAL RARCloseArchive(HANDLE hArcData)
  169 {
  170   DataSet *Data=(DataSet *)hArcData;
  171   try
  172   {
  173     bool Success=Data==NULL ? false:Data->Arc.Close();
  174     delete Data;
  175     return Success ? ERAR_SUCCESS : ERAR_ECLOSE;
  176   }
  177   catch (RAR_EXIT ErrCode)
  178   {
  179     return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
  180   }
  181 }
  182 
  183 
  184 int PASCAL RARReadHeader(HANDLE hArcData,struct RARHeaderData *D)
  185 {
  186   struct RARHeaderDataEx X;
  187   memset(&X,0,sizeof(X));
  188 
  189   int Code=RARReadHeaderEx(hArcData,&X);
  190 
  191   strncpyz(D->ArcName,X.ArcName,ASIZE(D->ArcName));
  192   strncpyz(D->FileName,X.FileName,ASIZE(D->FileName));
  193   D->Flags=X.Flags;
  194   D->PackSize=X.PackSize;
  195   D->UnpSize=X.UnpSize;
  196   D->HostOS=X.HostOS;
  197   D->FileCRC=X.FileCRC;
  198   D->FileTime=X.FileTime;
  199   D->UnpVer=X.UnpVer;
  200   D->Method=X.Method;
  201   D->FileAttr=X.FileAttr;
  202   D->CmtSize=0;
  203   D->CmtState=0;
  204 
  205   return Code;
  206 }
  207 
  208 
  209 int PASCAL RARReadHeaderEx(HANDLE hArcData,struct RARHeaderDataEx *D)
  210 {
  211   DataSet *Data=(DataSet *)hArcData;
  212   try
  213   {
  214     if ((Data->HeaderSize=(int)Data->Arc.SearchBlock(HEAD_FILE))<=0)
  215     {
  216       if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_ENDARC &&
  217           Data->Arc.EndArcHead.NextVolume)
  218         if (MergeArchive(Data->Arc,NULL,false,'L'))
  219         {
  220           Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
  221           return RARReadHeaderEx(hArcData,D);
  222         }
  223         else
  224           return ERAR_EOPEN;
  225 
  226       if (Data->Arc.BrokenHeader)
  227         return ERAR_BAD_DATA;
  228 
  229       // Might be necessary if RARSetPassword is still called instead of
  230       // open callback for RAR5 archives and if password is invalid.
  231       if (Data->Arc.FailedHeaderDecryption)
  232         return ERAR_BAD_PASSWORD;
  233       
  234       return ERAR_END_ARCHIVE;
  235     }
  236     FileHeader *hd=&Data->Arc.FileHead;
  237     if (Data->OpenMode==RAR_OM_LIST && hd->SplitBefore)
  238     {
  239       int Code=RARProcessFile(hArcData,RAR_SKIP,NULL,NULL);
  240       if (Code==0)
  241         return RARReadHeaderEx(hArcData,D);
  242       else
  243         return Code;
  244     }
  245     wcsncpy(D->ArcNameW,Data->Arc.FileName,ASIZE(D->ArcNameW));
  246     WideToChar(D->ArcNameW,D->ArcName,ASIZE(D->ArcName));
  247 
  248     wcsncpy(D->FileNameW,hd->FileName,ASIZE(D->FileNameW));
  249     WideToChar(D->FileNameW,D->FileName,ASIZE(D->FileName));
  250 #ifdef _WIN_ALL
  251     CharToOemA(D->FileName,D->FileName);
  252 #endif
  253 
  254     D->Flags=0;
  255     if (hd->SplitBefore)
  256       D->Flags|=RHDF_SPLITBEFORE;
  257     if (hd->SplitAfter)
  258       D->Flags|=RHDF_SPLITAFTER;
  259     if (hd->Encrypted)
  260       D->Flags|=RHDF_ENCRYPTED;
  261     if (hd->Solid)
  262       D->Flags|=RHDF_SOLID;
  263     if (hd->Dir)
  264       D->Flags|=RHDF_DIRECTORY;
  265 
  266     D->PackSize=uint(hd->PackSize & 0xffffffff);
  267     D->PackSizeHigh=uint(hd->PackSize>>32);
  268     D->UnpSize=uint(hd->UnpSize & 0xffffffff);
  269     D->UnpSizeHigh=uint(hd->UnpSize>>32);
  270     D->HostOS=hd->HSType==HSYS_WINDOWS ? HOST_WIN32:HOST_UNIX;
  271     D->UnpVer=Data->Arc.FileHead.UnpVer;
  272     D->FileCRC=hd->FileHash.CRC32;
  273     D->FileTime=hd->mtime.GetDos();
  274     
  275     uint64 MRaw=hd->mtime.GetWin();
  276     D->MtimeLow=(uint)MRaw;
  277     D->MtimeHigh=(uint)(MRaw>>32);
  278     uint64 CRaw=hd->ctime.GetWin();
  279     D->CtimeLow=(uint)CRaw;
  280     D->CtimeHigh=(uint)(CRaw>>32);
  281     uint64 ARaw=hd->atime.GetWin();
  282     D->AtimeLow=(uint)ARaw;
  283     D->AtimeHigh=(uint)(ARaw>>32);
  284 
  285     D->Method=hd->Method+0x30;
  286     D->FileAttr=hd->FileAttr;
  287     D->CmtSize=0;
  288     D->CmtState=0;
  289 
  290     D->DictSize=uint(hd->WinSize/1024);
  291 
  292     switch (hd->FileHash.Type)
  293     {
  294       case HASH_RAR14:
  295       case HASH_CRC32:
  296         D->HashType=RAR_HASH_CRC32;
  297         break;
  298       case HASH_BLAKE2:
  299         D->HashType=RAR_HASH_BLAKE2;
  300         memcpy(D->Hash,hd->FileHash.Digest,BLAKE2_DIGEST_SIZE);
  301         break;
  302       default:
  303         D->HashType=RAR_HASH_NONE;
  304         break;
  305     }
  306 
  307     D->RedirType=hd->RedirType;
  308     // RedirNameSize sanity check is useful in case some developer
  309     // did not initialize Reserved area with 0 as required in docs.
  310     // We have taken 'Redir*' fields from Reserved area. We may remove
  311     // this RedirNameSize check sometimes later.
  312     if (hd->RedirType!=FSREDIR_NONE && D->RedirName!=NULL &&
  313         D->RedirNameSize>0 && D->RedirNameSize<100000)
  314       wcsncpyz(D->RedirName,hd->RedirName,D->RedirNameSize);
  315     D->DirTarget=hd->DirTarget;
  316   }
  317   catch (RAR_EXIT ErrCode)
  318   {
  319     return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
  320   }
  321   return ERAR_SUCCESS;
  322 }
  323 
  324 
  325 int PASCAL ProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName,wchar *DestPathW,wchar *DestNameW)
  326 {
  327   DataSet *Data=(DataSet *)hArcData;
  328   try
  329   {
  330     Data->Cmd.DllError=0;
  331     if (Data->OpenMode==RAR_OM_LIST || Data->OpenMode==RAR_OM_LIST_INCSPLIT ||
  332         Operation==RAR_SKIP && !Data->Arc.Solid)
  333     {
  334       if (Data->Arc.Volume && Data->Arc.GetHeaderType()==HEAD_FILE &&
  335           Data->Arc.FileHead.SplitAfter)
  336         if (MergeArchive(Data->Arc,NULL,false,'L'))
  337         {
  338           Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
  339           return ERAR_SUCCESS;
  340         }
  341         else
  342           return ERAR_EOPEN;
  343       Data->Arc.SeekToNext();
  344     }
  345     else
  346     {
  347       Data->Cmd.DllOpMode=Operation;
  348 
  349       *Data->Cmd.ExtrPath=0;
  350       *Data->Cmd.DllDestName=0;
  351 
  352       if (DestPath!=NULL)
  353       {
  354         char ExtrPathA[NM];
  355         strncpyz(ExtrPathA,DestPath,ASIZE(ExtrPathA)-2);
  356 #ifdef _WIN_ALL
  357         // We must not apply OemToCharBuffA directly to DestPath,
  358         // because we do not know DestPath length and OemToCharBuffA
  359         // does not stop at 0.
  360         OemToCharA(ExtrPathA,ExtrPathA);
  361 #endif
  362         CharToWide(ExtrPathA,Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
  363         AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
  364       }
  365       if (DestName!=NULL)
  366       {
  367         char DestNameA[NM];
  368         strncpyz(DestNameA,DestName,ASIZE(DestNameA)-2);
  369 #ifdef _WIN_ALL
  370         // We must not apply OemToCharBuffA directly to DestName,
  371         // because we do not know DestName length and OemToCharBuffA
  372         // does not stop at 0.
  373         OemToCharA(DestNameA,DestNameA);
  374 #endif
  375         CharToWide(DestNameA,Data->Cmd.DllDestName,ASIZE(Data->Cmd.DllDestName));
  376       }
  377 
  378       if (DestPathW!=NULL)
  379       {
  380         wcsncpy(Data->Cmd.ExtrPath,DestPathW,ASIZE(Data->Cmd.ExtrPath));
  381         AddEndSlash(Data->Cmd.ExtrPath,ASIZE(Data->Cmd.ExtrPath));
  382       }
  383 
  384       if (DestNameW!=NULL)
  385         wcsncpyz(Data->Cmd.DllDestName,DestNameW,ASIZE(Data->Cmd.DllDestName));
  386 
  387       wcsncpyz(Data->Cmd.Command,Operation==RAR_EXTRACT ? L"X":L"T",ASIZE(Data->Cmd.Command));
  388       Data->Cmd.Test=Operation!=RAR_EXTRACT;
  389       bool Repeat=false;
  390       Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
  391 
  392       // Now we process extra file information if any.
  393       //
  394       // Archive can be closed if we process volumes, next volume is missing
  395       // and current one is already removed or deleted. So we need to check
  396       // if archive is still open to avoid calling file operations on
  397       // the invalid file handle. Some of our file operations like Seek()
  398       // process such invalid handle correctly, some not.
  399       while (Data->Arc.IsOpened() && Data->Arc.ReadHeader()!=0 && 
  400              Data->Arc.GetHeaderType()==HEAD_SERVICE)
  401       {
  402         Data->Extract.ExtractCurrentFile(Data->Arc,Data->HeaderSize,Repeat);
  403         Data->Arc.SeekToNext();
  404       }
  405       Data->Arc.Seek(Data->Arc.CurBlockPos,SEEK_SET);
  406     }
  407   }
  408   catch (std::bad_alloc&)
  409   {
  410     return ERAR_NO_MEMORY;
  411   }
  412   catch (RAR_EXIT ErrCode)
  413   {
  414     return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode);
  415   }
  416   return Data->Cmd.DllError;
  417 }
  418 
  419 
  420 int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName)
  421 {
  422   return ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL);
  423 }
  424 
  425 
  426 int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName)
  427 {
  428   return ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName);
  429 }
  430 
  431 
  432 void PASCAL RARSetChangeVolProc(HANDLE hArcData,CHANGEVOLPROC ChangeVolProc)
  433 {
  434   DataSet *Data=(DataSet *)hArcData;
  435   Data->Cmd.ChangeVolProc=ChangeVolProc;
  436 }
  437 
  438 
  439 void PASCAL RARSetCallback(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData)
  440 {
  441   DataSet *Data=(DataSet *)hArcData;
  442   Data->Cmd.Callback=Callback;
  443   Data->Cmd.UserData=UserData;
  444 }
  445 
  446 
  447 void PASCAL RARSetProcessDataProc(HANDLE hArcData,PROCESSDATAPROC ProcessDataProc)
  448 {
  449   DataSet *Data=(DataSet *)hArcData;
  450   Data->Cmd.ProcessDataProc=ProcessDataProc;
  451 }
  452 
  453 
  454 void PASCAL RARSetPassword(HANDLE hArcData,char *Password)
  455 {
  456 #ifndef RAR_NOCRYPT
  457   DataSet *Data=(DataSet *)hArcData;
  458   wchar PasswordW[MAXPASSWORD];
  459   GetWideName(Password,NULL,PasswordW,ASIZE(PasswordW));
  460   Data->Cmd.Password.Set(PasswordW);
  461   cleandata(PasswordW,sizeof(PasswordW));
  462 #endif
  463 }
  464 
  465 
  466 int PASCAL RARGetDllVersion()
  467 {
  468   return RAR_DLL_VERSION;
  469 }
  470 
  471 
  472 static int RarErrorToDll(RAR_EXIT ErrCode)
  473 {
  474   switch(ErrCode)
  475   {
  476     case RARX_FATAL:
  477     case RARX_READ:
  478       return ERAR_EREAD;
  479     case RARX_CRC:
  480       return ERAR_BAD_DATA;
  481     case RARX_WRITE:
  482       return ERAR_EWRITE;
  483     case RARX_OPEN:
  484       return ERAR_EOPEN;
  485     case RARX_CREATE:
  486       return ERAR_ECREATE;
  487     case RARX_MEMORY:
  488       return ERAR_NO_MEMORY;
  489     case RARX_BADPWD:
  490       return ERAR_BAD_PASSWORD;
  491     case RARX_SUCCESS:
  492       return ERAR_SUCCESS; // 0.
  493     default:
  494       return ERAR_UNKNOWN;
  495   }
  496 }