home *** CD-ROM | disk | FTP | other *** search
/ ftp.rarlab.com / 2014.05.ftp.rarlab.com.tar / ftp.rarlab.com / rar / farfmt.rar / rar.cpp next >
C/C++ Source or Header  |  2013-06-03  |  11KB  |  353 lines

  1. /*
  2.   RAR.CPP
  3.  
  4.   Second-level plugin module for FAR Manager and MultiArc plugin
  5.  
  6.   Copyright (c) 1996 Eugene Roshal
  7.   Copyrigth (c) 2000 FAR group
  8. */
  9.  
  10. #define STRICT
  11.  
  12. #include <windows.h>
  13. #include <string.h>
  14. #include <dos.h>
  15. #include <CRT/crt.hpp>
  16. #include <plugin.hpp>
  17. #include "fmt.hpp"
  18. #include "marclng.hpp"
  19. #include "unrar.h"
  20.  
  21. #if defined(__BORLANDC__)
  22.   #pragma option -a1
  23. #elif defined(__GNUC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1100)) || defined(__LCC__)
  24.   #pragma pack(1)
  25. #else
  26.   #pragma pack(push,1)
  27. #endif
  28.  
  29. #if defined(__GNUC__)
  30. #ifdef __cplusplus
  31. extern "C"{
  32. #endif
  33.   BOOL WINAPI DllMainCRTStartup(HANDLE hDll,DWORD dwReason,LPVOID lpReserved);
  34. #ifdef __cplusplus
  35. };
  36. #endif
  37.  
  38. BOOL WINAPI DllMainCRTStartup(HANDLE hDll,DWORD dwReason,LPVOID lpReserved)
  39. {
  40.   (void) lpReserved;
  41.   (void) dwReason;
  42.   (void) hDll;
  43.   return TRUE;
  44. }
  45. #endif
  46.  
  47. #define  LHD_LARGE          0x0100
  48. #define  LHD_UNICODE        0x0200
  49. #define  LHD_SALT           0x0400
  50. #define  LHD_EXTTIME        0x1000
  51. #define  LHD_WINDOWMASK     0x00e0
  52. #define  LHD_DIRECTORY      0x00e0
  53. #define  LONG_BLOCK         0x8000
  54.  
  55. enum HEADER_TYPE {
  56.   MARK_HEAD=0x72,
  57.   MAIN_HEAD=0x73,
  58.   FILE_HEAD=0x74,
  59.   COMM_HEAD=0x75,
  60.   AV_HEAD=0x76,
  61.   SUB_HEAD=0x77,
  62.   PROTECT_HEAD=0x78,
  63.   SIGN_HEAD=0x79,
  64.   NEWSUB_HEAD=0x7a,
  65.   ENDARC_HEAD=0x7b
  66. };
  67.  
  68. typedef HANDLE (PASCAL *RAROPENARCHIVEEX)(struct RAROpenArchiveDataEx *ArchiveData);
  69. typedef int (PASCAL *RARCLOSEARCHIVE)(HANDLE hArcData);
  70. typedef void (PASCAL *RARSETCALLBACK)(HANDLE hArcData,UNRARCALLBACK Callback,LPARAM UserData);
  71. typedef int (PASCAL *RARREADHEADEREX)(HANDLE hArcData,struct RARHeaderDataEx *HeaderData);
  72. typedef int (PASCAL *RARPROCESSFILE)(HANDLE hArcData,int Operation,char *DestPath,char *DestName);
  73.  
  74. #ifndef _WIN64
  75. const char UnRARName[]="UNRAR.DLL";
  76. #else
  77. const char UnRARName[]="UNRAR64.DLL";
  78. #endif
  79. static const char * const RarOS[]={"DOS","OS/2","Windows","Unix","MacOS","BeOS"};
  80.  
  81. static HANDLE ArcHandle;
  82. static DWORD NextPosition,SFXSize,FileSize,FileSizeHigh,Flags;
  83. static long NextPositionHigh;
  84. static int RarFormat=15;
  85. static bool MissingVolume;
  86.  
  87. static BOOL UsedUnRAR_DLL=FALSE;
  88. static HANDLE hArcData;
  89. static int RHCode,PFCode;
  90. static struct RAROpenArchiveDataEx OpenArchiveData;
  91. static struct RARHeaderDataEx HeaderData;
  92.  
  93. static RAROPENARCHIVEEX pRAROpenArchiveEx=NULL;
  94. static RARCLOSEARCHIVE pRARCloseArchive=NULL;
  95. static RARSETCALLBACK pRARSetCallback=NULL;
  96. static RARREADHEADEREX pRARReadHeaderEx=NULL;
  97. static RARPROCESSFILE pRARProcessFile=NULL;
  98.  
  99. static char Password[NM/2];
  100.  
  101. static FARAPIINPUTBOX FarInputBox=NULL;
  102. static FARAPIGETMSG   FarGetMsg=NULL;
  103. static INT_PTR MainModuleNumber=-1;
  104. static FARAPIMESSAGE FarMessage=NULL;
  105. static FARSTDSPRINTF FarSprintf=NULL;
  106.  
  107. void UtfToWide(const char *Src,wchar_t *Dest,int DestSize);
  108. void DecodeFileName(const char *Name,BYTE *EncName,int EncSize,wchar_t *NameW,int MaxDecSize);
  109. #define UnicodeToOEM(src,dst,lendst)    WideCharToMultiByte(CP_OEMCP,0,(src),-1,(dst),(lendst),NULL,FALSE)
  110. #define  Min(x,y) (((x)<(y)) ? (x):(y))
  111.  
  112.  
  113. void  WINAPI SetFarInfo(const struct PluginStartupInfo *Info)
  114. {
  115.    FarInputBox=Info->InputBox;
  116.    FarGetMsg=Info->GetMsg;
  117.    MainModuleNumber=Info->ModuleNumber;
  118.    FarMessage=Info->Message;
  119.    FarSprintf=Info->FSF->sprintf;
  120. }
  121.  
  122. int CALLBACK CallbackProc(UINT msg,LPARAM UserData,LPARAM P1,LPARAM P2)
  123. {
  124.   switch(msg)
  125.   {
  126.     case UCM_NEEDPASSWORD:
  127.     {
  128.       if(FarInputBox(FarGetMsg(MainModuleNumber,MGetPasswordTitle),
  129.                      FarGetMsg(MainModuleNumber,MGetPassword),NULL,
  130.                      Password,Password,sizeof(Password)-1,NULL,FIB_PASSWORD))
  131.       {
  132.         OemToChar(Password, Password);
  133.         lstrcpyn((char *)P1,Password,(int)P2);
  134.         return 1;
  135.       }
  136.       return -1;
  137.     }
  138.     case UCM_CHANGEVOLUMEW: // Do not hang if volume is missing.
  139.     {
  140.       if (P2==RAR_VOL_ASK)
  141.       {
  142.         LPCTSTR Msg[]={FarGetMsg(MainModuleNumber,MError),"Volume is missing"};
  143.         FarMessage(MainModuleNumber,FMSG_WARNING|FMSG_MB_OK,NULL,Msg,sizeof(Msg)/sizeof(*Msg),0);
  144.         MissingVolume=true;
  145.         return -1;
  146.       }
  147.     }
  148.   }
  149.   return 0;
  150. }
  151.  
  152. BOOL WINAPI _export IsArchive(const char *Name,const unsigned char *Data,int DataSize)
  153. {
  154.   for (int I=0;I<DataSize-9;I++)
  155.   {
  156.     const unsigned char *D=Data+I;
  157.     if (D[0]==0x52 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e &&
  158.         (I==0 || (DataSize>31 && Data[28]==0x52 && Data[29]==0x53 &&
  159.         Data[30]==0x46 && Data[31]==0x58)))
  160.     {
  161.       RarFormat = 14; // RAR 1.4 archive format.
  162.       SFXSize=I;
  163.       return TRUE;
  164.     }
  165.     // check marker block
  166.     // The marker block is actually considered as a fixed byte sequence: 0x52 0x61 0x72 0x21 0x1a 0x07 0x00
  167.     if (D[0]==0x52 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 &&
  168.         D[4]==0x1a && D[5]==0x07 && 
  169.         (D[6]==0 && D[9]==0x73 || // RAR 1.5 signature followed by main archive header (Header type: 0x73)
  170.          D[6]==1 && D[7]==0))     // RAR 5.0 signature.
  171.     {
  172.       RarFormat=D[6]==0 ? 15 : 50; // RAR 1.5 or 5.0 archive format.
  173.       SFXSize=I;
  174.       return TRUE;
  175.     }
  176.   }
  177.   return FALSE;
  178. }
  179.  
  180.  
  181. BOOL WINAPI _export OpenArchive(const char *Name,int *Type)
  182. {
  183.   UsedUnRAR_DLL=FALSE;
  184.   MissingVolume=false;
  185.  
  186.   // We attempt to load unrar.dll first from "Plugins\MultiArc\Formats"
  187.   // and then from root FAR folder. We use absolute paths for security reason.
  188.   char DllName[NM+50];
  189.   GetModuleFileName(NULL,DllName,sizeof(DllName)/sizeof(DllName[0]));
  190.   char *NamePtr=strrchr(DllName,'\\');
  191.   NamePtr=(NamePtr==NULL) ? DllName:NamePtr+1;
  192.   lstrcpy(NamePtr,"Plugins\\MultiArc\\Formats\\");
  193.   lstrcat(NamePtr,UnRARName);
  194.  
  195.   HINSTANCE hModule=LoadLibraryEx(DllName,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
  196.   if (hModule==NULL)
  197.   {
  198.     strcpy(NamePtr,UnRARName);
  199.     hModule=LoadLibraryEx(DllName,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
  200.   }
  201.  
  202.   if (hModule!=NULL)
  203.   {
  204.     pRAROpenArchiveEx=(RAROPENARCHIVEEX)GetProcAddress(hModule,"RAROpenArchiveEx");
  205.     pRARCloseArchive =(RARCLOSEARCHIVE )GetProcAddress(hModule,"RARCloseArchive");
  206.     pRARSetCallback  =(RARSETCALLBACK  )GetProcAddress(hModule,"RARSetCallback");
  207.     pRARReadHeaderEx =(RARREADHEADEREX )GetProcAddress(hModule,"RARReadHeaderEx");
  208.     pRARProcessFile  =(RARPROCESSFILE  )GetProcAddress(hModule,"RARProcessFile");
  209.  
  210.     if (pRAROpenArchiveEx && pRARCloseArchive && pRARSetCallback && pRARReadHeaderEx && pRARProcessFile)
  211.       UsedUnRAR_DLL=TRUE;
  212.     else
  213.       FreeLibrary(hModule);
  214.   }
  215.  
  216.   if (!UsedUnRAR_DLL)
  217.   {
  218.     TCHAR ErrStr[1024];
  219.     FarSprintf(ErrStr,FarGetMsg(MainModuleNumber,MCannotFindArchivator),UnRARName);
  220.     LPCTSTR Msg[]={FarGetMsg(MainModuleNumber,MError),ErrStr};
  221.     FarMessage(MainModuleNumber,FMSG_WARNING|FMSG_MB_OK,NULL,Msg,sizeof(Msg)/sizeof(*Msg),0);
  222.     return FALSE;
  223.   }
  224.  
  225.   memset(&OpenArchiveData,0,sizeof(OpenArchiveData));
  226.   OpenArchiveData.ArcName=(char*)Name;
  227.   OpenArchiveData.OpenMode=RAR_OM_LIST;
  228.   OpenArchiveData.Callback=CallbackProc;
  229.   hArcData=pRAROpenArchiveEx(&OpenArchiveData);
  230.   if (OpenArchiveData.OpenResult!=0)
  231.     return FALSE;
  232.  
  233.   Flags=OpenArchiveData.Flags;
  234.   memset(&HeaderData,0,sizeof(HeaderData));
  235.   return TRUE;
  236. }
  237.  
  238.  
  239. int WINAPI _export GetArcItem(struct PluginPanelItem *Item,struct ArcItemInfo *Info)
  240. {
  241.   RHCode=pRARReadHeaderEx(hArcData,&HeaderData);
  242.   if (RHCode!=0)
  243.     return RHCode==ERAR_BAD_DATA && !MissingVolume ? GETARC_BROKEN : GETARC_EOF;
  244.  
  245.   UnicodeToOEM(HeaderData.FileNameW,Item->FindData.cFileName,sizeof(Item->FindData.cFileName)-1);
  246.   //lstrcpyn(Item->FindData.cFileName,HeaderData.FileName,sizeof(Item->FindData.cFileName)-1);
  247.  
  248.   if (HeaderData.HostOS==3) // Unix.
  249.     Item->FindData.dwFileAttributes=(HeaderData.Flags & RHDF_DIRECTORY)!=0 ? 0x10:0;
  250.   else
  251.     Item->FindData.dwFileAttributes=HeaderData.FileAttr;
  252.   Item->FindData.nFileSizeLow=HeaderData.UnpSize;
  253.   Item->FindData.nFileSizeHigh=HeaderData.UnpSizeHigh;
  254.   Item->PackSizeHigh=HeaderData.PackSizeHigh;
  255.   Item->PackSize=HeaderData.PackSize;
  256.   Item->CRC32=(DWORD)HeaderData.FileCRC;
  257.   FILETIME lft;
  258.   DosDateTimeToFileTime(HIWORD(HeaderData.FileTime),LOWORD(HeaderData.FileTime),&lft);
  259.   LocalFileTimeToFileTime(&lft,&Item->FindData.ftLastWriteTime);
  260.  
  261.   static const char* const RarOS[]={"DOS","OS/2","Windows","Unix"};
  262.   if (HeaderData.HostOS<ArraySize(RarOS))
  263.     lstrcpy(Info->HostOS,RarOS[HeaderData.HostOS]);
  264.   Info->Solid=Flags & 8;
  265.   Info->Comment=HeaderData.Flags & 8;
  266.   Info->Encrypted=HeaderData.Flags & 4;
  267.   Info->DictSize=HeaderData.DictSize;
  268.   Info->UnpVer=(HeaderData.UnpVer/10)*256+(HeaderData.UnpVer%10);
  269.  
  270.   if ((PFCode=pRARProcessFile(hArcData,RAR_SKIP,NULL,NULL))!=0)
  271.   {
  272.     if (MissingVolume)
  273.       return GETARC_EOF;
  274.     return RHCode==ERAR_BAD_DATA ? GETARC_BROKEN : GETARC_READERROR;
  275.   }
  276.  
  277.   return GETARC_SUCCESS;
  278. }
  279.  
  280.  
  281. BOOL WINAPI _export CloseArchive(struct ArcInfo *Info)
  282. {
  283.   Info->SFXSize=SFXSize;
  284.   Info->Volume=Flags & 1;
  285.   Info->Comment=Flags & 2;
  286.   Info->Lock=Flags & 4;
  287.   Info->Recovery=Flags & 64;
  288.  
  289.   if (Flags & 32)
  290.     Info->Flags|=AF_AVPRESENT;
  291.   if (Flags & 0x80)
  292.     Info->Flags|=AF_HDRENCRYPTED;
  293.  
  294.   *Password=0;
  295.  
  296.   if (UsedUnRAR_DLL)
  297.     return pRARCloseArchive(hArcData);
  298.  
  299.   return CloseHandle(ArcHandle);
  300. }
  301.  
  302. DWORD WINAPI _export GetSFXPos()
  303. {
  304.   return SFXSize;
  305. }
  306.  
  307.  
  308. BOOL WINAPI _export GetFormatName(int Type,char *FormatName,char *DefaultExt)
  309. {
  310.   if (Type==0)
  311.   {
  312. // Plugin "Save settings" does not work well if we return different format names.
  313. //    lstrcpy(FormatName,RarFormat==14 ? "RAR1.4":(RarFormat==15 ? "RAR4":"RAR5"));
  314.     lstrcpy(FormatName,"RAR"); 
  315.     lstrcpy(DefaultExt,"rar");
  316.     return(TRUE);
  317.   }
  318.   return(FALSE);
  319. }
  320.  
  321.  
  322.  
  323. BOOL WINAPI _export GetDefaultCommands(int Type,int Command,char *Dest)
  324. {
  325.   if (Type==0)
  326.   {
  327.     // Console RAR 5.0 commands
  328.     static const char *Commands[]={
  329.     /*Extract               */"rar x {-p%%P} {-ap%%R} -y -c- -kb -- %%A @%%LNMA",
  330.     /*Extract without paths */"rar e {-p%%P} -y -c- -kb -- %%A @%%LNMA",
  331.     /*Test                  */"rar t -y {-p%%P} -- %%A",
  332.     /*Delete                */"rar d -y {-w%%W} -- %%A @%%LNMA",
  333.     /*Comment archive       */"rar c -y {-w%%W} -- %%A",
  334.     /*Comment files         */"",
  335.     /*Convert to SFX        */"rar s -y -- %%A",
  336.     /*Lock archive          */"rar k -y -- %%A",
  337.     /*Protect archive       */"rar rr -y -- %%A",
  338.     /*Recover archive       */"rar r -y -- %%A",
  339.     /*Add files             */"rar a -y {-p%%P} {-ap%%R} {-w%%W} {%%S} -- %%A @%%LNA",
  340.     /*Move files            */"rar m -y {-p%%P} {-ap%%R} {-w%%W} {%%S} -- %%A @%%LNA",
  341.     /*Add files and folders */"rar a -r0 -y {-p%%P} {-ap%%R} {-w%%W} {%%S} -- %%A @%%LNA",
  342.     /*Move files and folders*/"rar m -r0 -y {-p%%P} {-ap%%R} {-w%%W} {%%S} -- %%A @%%LNA",
  343.     /*"All files" mask      */"*.*"
  344.     };
  345.     if (Command<(int)(ArraySize(Commands)))
  346.     {
  347.       lstrcpy(Dest,Commands[Command]);
  348.       return(TRUE);
  349.     }
  350.   }
  351.   return(FALSE);
  352. }
  353.