home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / varie / xad / developer / sources / tools / exe2arc.c next >
Encoding:
C/C++ Source or Header  |  2000-06-25  |  14.6 KB  |  589 lines

  1. #define NAME         "exe2arc"
  2. #define DISTRIBUTION "(Freeware) "
  3. #define REVISION     "2"
  4. #define DATE         "29.05.2000"
  5.  
  6. /* Programmheader
  7.  
  8.     Name:        exe2arc
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    strips executable header from exe files
  12.     Compileropts:    -
  13.     Linkeropts:    -gsi -l amiga
  14.  
  15.  1.0   02.11.99 : first version
  16.  1.1   06.11.99 : now also supports zip exes with wrong offsets
  17.  1.2   29.05.00 : renamed from exe2zip, added Ace, Rar, Cab, Arj, LhA
  18. */
  19.  
  20. #include <proto/exec.h>
  21. #include <proto/dos.h>
  22. #include <exec/memory.h>
  23. #include "SDI_version.h"
  24.  
  25. struct DosLibrary *     DOSBase = 0;
  26. struct ExecBase *     SysBase  = 0;
  27.  
  28. #define PARAM    "FROM/A,TO"
  29.  
  30. struct Args {
  31.   STRPTR   from;
  32.   STRPTR   to;
  33. };
  34.  
  35. #define BUFSIZE 102400
  36.  
  37. #define EndConvI32(a)    (((a)>>24)|(((a)>>8)&0xFF00)|(((a)<<8)&0xFF0000)|((a)<<24))
  38. #define EndConvI16(a)    ((UWORD)(((a)>>8)|((a)<<8)))
  39.  
  40. typedef BOOL (* SCANFUNC)(BPTR infh, STRPTR buffer, ULONG filesize, ULONG buffersize);
  41. typedef ULONG (* EXTRACTFUNC)(BPTR infh, BPTR outfh, STRPTR buffer, ULONG filesize, ULONG buffersize);
  42.  
  43. struct ScanData {
  44.   SCANFUNC    ScanFunc;
  45.   EXTRACTFUNC    ExtractFunc;
  46.   STRPTR    Extension;
  47.   STRPTR    Name;
  48. };
  49.  
  50. /* a) It is not the very best method to do scan loop again and again, but easy
  51.       to implement :-)
  52.    b) The buffer can be used to pass data from scanner to extractor.
  53. */
  54.  
  55. struct ScanData ScanFuncs[]; /* declaration, real field see file end */
  56.  
  57. ULONG start(void)
  58. {
  59.   ULONG ret = RETURN_FAIL;
  60.   struct DosLibrary *dosbase;
  61.  
  62.   SysBase = (*((struct ExecBase **) 4));
  63.   { /* test for WB and reply startup-message */
  64.     struct Process *task;
  65.     if(!(task = (struct Process *) FindTask(0))->pr_CLI)
  66.     {
  67.       WaitPort(&task->pr_MsgPort);
  68.       Forbid();
  69.       ReplyMsg(GetMsg(&task->pr_MsgPort));
  70.       return RETURN_FAIL;
  71.     }
  72.   }
  73.  
  74.   if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  75.   {
  76.     struct Args args;
  77.     struct RDArgs *rda;
  78.  
  79.     DOSBase = dosbase;
  80.  
  81.     args.to = 0;
  82.     if((rda = ReadArgs(PARAM, (LONG *) &args, 0)))
  83.     {
  84.       BPTR infh;
  85.  
  86.       if((infh = Open(args.from, MODE_OLDFILE)))
  87.       {
  88.         struct FileInfoBlock *fib;
  89.  
  90.         if((fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)))
  91.         {
  92.           if(ExamineFH(infh, fib))
  93.           {
  94.             STRPTR buf;
  95.  
  96.             if((buf = AllocMem(BUFSIZE+512, MEMF_ANY)))
  97.             {
  98.           ULONG i, j;
  99.           LONG stop = 0;
  100.  
  101.           for(i = 0; !stop && ScanFuncs[i].ScanFunc; ++i)
  102.           {
  103.                 if(Seek(infh, 0, OFFSET_BEGINNING) >= 0)
  104.                 {
  105.                   Printf("Scanning for %s-Archive.", ScanFuncs[i].Name);
  106.                   Flush(Output());
  107.                   if(ScanFuncs[i].ScanFunc(infh, buf, fib->fib_Size, BUFSIZE))
  108.                   {
  109.                     BPTR outfh;
  110.                     if(!args.to)
  111.                     {
  112.                       STRPTR tmp = buf+BUFSIZE;
  113.                       ULONG k;
  114.  
  115.                       args.to = tmp;
  116.                       for(j = 0; args.from[j]; ++j)
  117.                         tmp[j] = args.from[j];
  118.               k = j;
  119.  
  120.               do
  121.               {
  122.                 if(tmp[--j] == '.')
  123.                   k = j;
  124.               } while(j && tmp[j] != '.' && tmp[j] != '/' && tmp[j] != ':');
  125.               tmp[k++] = '.';
  126.               for(j = 0; ScanFuncs[i].Extension[j]; ++j)
  127.                 tmp[k++] = ScanFuncs[i].Extension[j];
  128.               tmp[k] = 0;
  129.                     }
  130.                     stop = 1;
  131.             Printf(" Found.\n");
  132.                     if((outfh = Open(args.to, MODE_NEWFILE)))
  133.                     {
  134.                       if((j = ScanFuncs[i].ExtractFunc(infh, outfh, buf, fib->fib_Size, BUFSIZE)))
  135.                       {
  136.                         Printf("Saved %ld byte to %s\nBe careful and test the file for correctness.\n", j, args.to);
  137.                         ret = 0;
  138.                       }
  139.                       Close(outfh);
  140.                       if(ret)
  141.                         DeleteFile(args.to);
  142.                     }
  143.                     else
  144.                       Printf("\nFailed to open output file.\n");
  145.                   }
  146.                   else
  147.                   {
  148.                     Printf("\r\033[K");
  149.                     Flush(Output());
  150.                   }
  151.                 }
  152.                 else
  153.                 {
  154.                   stop = 1;
  155.                   Printf("Failed to seek to file start.\n");
  156.                 }
  157.               }
  158.               if(!stop)
  159.                  Printf("\r\033[KDid not find archive data.\n");
  160.               FreeMem(buf, BUFSIZE+512);
  161.             }
  162.             else
  163.               Printf("Failed to open temporary buffer.\n");
  164.           }
  165.           else
  166.             Printf("Failed to examine file.\n");
  167.           FreeDosObject(DOS_FIB, 0);
  168.         }
  169.         else
  170.           Printf("Failed to open file information object.\n");
  171.         Close(infh);
  172.       }
  173.       else
  174.         Printf("Failed to open input file.\n");
  175.       FreeArgs(rda);
  176.     }
  177.     else
  178.       PrintFault(IoErr(), 0);
  179.     CloseLibrary((struct Library *) dosbase);
  180.   } /* OpenLibrary dos */
  181.   return ret;
  182. }
  183.  
  184. ULONG DoCopy(BPTR infh, BPTR outfh, STRPTR buf, ULONG size, ULONG buffersize)
  185. {
  186.   ULONG s, err = 0;
  187.   
  188.   while(size && !err)
  189.   {
  190.     s = size;
  191.     if(s > buffersize)
  192.       s = buffersize;
  193.     if(Read(infh, buf, s) != s)
  194.       err = RETURN_FAIL;
  195.     else if(Write(outfh, buf, s) != s)
  196.       err = RETURN_FAIL;
  197.     size -= s;
  198.   }
  199.   
  200.   return err;
  201. }
  202.  
  203. /******** exe2zip *********/
  204.  
  205. BOOL ScanZIP(BPTR fh, STRPTR buf, ULONG size, ULONG bufsize)
  206. {
  207.   ULONG start = 0, corr = 0;
  208.   LONG stop = 0, i, j, k;
  209.  
  210.   if(Seek(fh, 0, OFFSET_END) >= 0)
  211.   {
  212.     while(size > 22 && !stop)
  213.     {
  214.       if(bufsize > size)
  215.         bufsize = size;
  216.       if(Seek(fh, size-bufsize, OFFSET_BEGINNING) < 0)
  217.         ++stop;
  218.       else if(Read(fh, buf, bufsize) != bufsize)
  219.         ++stop;
  220.       for(i = bufsize-22; i >= 0 && !stop; --i)
  221.       {
  222.         if(buf[i] == 'P' && buf[i+1] == 'K' && buf[i+2] == 5 && buf[i+3] == 6)
  223.         {
  224.           j = (((((buf[i+19]<<8)+buf[i+18])<<8)+buf[i+17])<<8)+buf[i+16];
  225.           k = (((((buf[i+15]<<8)+buf[i+14])<<8)+buf[i+13])<<8)+buf[i+12];
  226.           if(j != size-bufsize+i-k)
  227.       {
  228.         corr = (size-bufsize+i-k)-j;
  229.         j += corr;
  230.       }
  231.           if(Seek(fh, j+4, OFFSET_BEGINNING) >= 0)
  232.           {
  233.             if(Read(fh, buf, 42) == 42)
  234.               start = ((buf[38]) | (buf[39]<<8) | (buf[40]<<16) | (buf[41]<<24)) + corr;
  235.           }
  236.           ++stop;
  237.         }
  238.       }
  239.       size -= (bufsize-21);
  240.     }
  241.   }
  242.  
  243.   if(start)
  244.     Seek(fh, start, OFFSET_BEGINNING);
  245.   ((ULONG *)buf)[0] = corr; /* store this for extract */
  246.   ((ULONG *)buf)[1] = start;
  247.  
  248.   return (BOOL) (start ? TRUE : FALSE);
  249. }
  250.  
  251. ULONG ExtractZIP(BPTR infh, BPTR outfh, STRPTR buf, ULONG filesize, ULONG buffersize)
  252. {
  253.   LONG start, corr, Type = 0, ret = 0, i;
  254.  
  255.   start = ((ULONG *)buf)[1];
  256.   corr = ((ULONG *)buf)[0]-start;
  257.  
  258.   while(Type != 0x504B0506 && !ret && !(SetSignal(0L,0L) & SIGBREAKF_CTRL_C))
  259.   {
  260.     if(Read(infh, &Type, 4) == 4)
  261.     {
  262.       ret = RETURN_FAIL;
  263.       switch(Type)
  264.       {
  265.       case 0x504B0304: /* local */
  266.         if(Read(infh, buf+4, 26) == 26)
  267.         {
  268.           buf[0] = 'P'; buf[1] = 'K'; buf[2] = 3; buf[3] = 4;
  269.           if(Write(outfh, buf, 30) == 30)
  270.           {
  271.             ret = DoCopy(infh, outfh, buf, ((buf[18]) | (buf[19]<<8) | (buf[20]<<16) | (buf[21]<<24)) +
  272.             ((buf[26]) | (buf[27]<<8)) + ((buf[28]) | (buf[29]<<8)), buffersize);
  273.           }
  274.         }
  275.         break;
  276.       case 0x504B0102: /* central */
  277.         if(Read(infh, buf+4, 42) == 42)
  278.         {
  279.           buf[0] = 'P'; buf[1] = 'K'; buf[2] = 1; buf[3] = 2;
  280.           i = ((buf[42]) | (buf[43]<<8) | (buf[44]<<16) | (buf[45]<<24)) + corr;
  281.       buf[42] = i;
  282.       buf[43] = i>>8;
  283.       buf[44] = i>>16;
  284.       buf[45] = i>>24;
  285.           if(Write(outfh, buf, 46) == 46)
  286.           {
  287.             ret = DoCopy(infh, outfh, buf, ((buf[28]) | (buf[29]<<8)) +
  288.             ((buf[30]) | (buf[31]<<8)) + ((buf[32]) | (buf[33]<<8)), buffersize);
  289.           }
  290.         }
  291.         break;
  292.       case 0x504B0506: /* end */
  293.         if(Read(infh, buf+4, 18) == 18)
  294.         {
  295.           buf[0] = 'P'; buf[1] = 'K'; buf[2] = 5; buf[3] = 6;
  296.           i = ((buf[16]) | (buf[17]<<8) | (buf[18]<<16) | (buf[19]<<24)) + corr;
  297.       buf[16] = i;
  298.       buf[17] = i>>8;
  299.       buf[18] = i>>16;
  300.       buf[19] = i>>24;
  301.           if(Write(outfh, buf, 22) == 22)
  302.             ret = DoCopy(infh, outfh, buf, buf[20] | (buf[21]<<8), buffersize); /* copy comment */
  303.         }
  304.         break;
  305.       default:
  306.     Printf("Unknown or illegal data found.\n");
  307.     break;
  308.       }
  309.     }
  310.     else
  311.       Printf("Unexpected end of data.\n");
  312.   }
  313.   if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
  314.     SetIoErr(ERROR_BREAK);
  315.  
  316.   return ret ? 0 : filesize-start;
  317. }
  318.  
  319. /******** exe2ace *********/
  320.  
  321. BOOL ScanACE(BPTR fh, STRPTR buf, ULONG size, ULONG bufsize)
  322. {
  323.   ULONG start = 0;
  324.   LONG i, pos = 0, stop = 0;
  325.  
  326.   while(size > 14 && !stop)
  327.   {
  328.     if(bufsize > size)
  329.       bufsize = size;
  330.     if(Seek(fh, pos, OFFSET_BEGINNING) < 0)
  331.       ++stop;
  332.     else if(Read(fh, buf, bufsize) != bufsize)
  333.       ++stop;
  334.     for(i = 0; i <= bufsize-14 && !stop; ++i)
  335.     {
  336.       if(buf[i+7] == '*' && buf[i+8] == '*' && buf[i+9] == 'A' && buf[i+10] == 'C' &&
  337.       buf[i+11] == 'E' && buf[i+12] == '*' && buf[i+13] == '*')
  338.       {
  339.         if(Seek(fh, -i, OFFSET_CURRENT) >= 0)
  340.           start = pos+i;
  341.         ++stop;
  342.       }
  343.     }
  344.     size -= i;
  345.     pos += i;
  346.   }
  347.  
  348.   if(start)
  349.     Seek(fh, start, OFFSET_BEGINNING);
  350.   ((ULONG *)buf)[0] = start;
  351.  
  352.   return (BOOL) (start ? TRUE : FALSE);
  353. }
  354.  
  355. ULONG ExtractACE(BPTR infh, BPTR outfh, STRPTR buf, ULONG filesize, ULONG buffersize)
  356. {
  357.   LONG ret;
  358.  
  359.   filesize -= ((ULONG *)buf)[0];
  360.   ret = DoCopy(infh, outfh, buf, filesize, buffersize);
  361.   
  362.   return ret ? 0 : filesize;
  363. }
  364.  
  365. /******** exe2rar *********/
  366.  
  367. BOOL ScanRAR(BPTR fh, STRPTR buf, ULONG size, ULONG bufsize)
  368. {
  369.   ULONG start = 0;
  370.   LONG i, pos = 0, stop = 0;
  371.  
  372.   while(size > 7 && !stop)
  373.   {
  374.     if(bufsize > size)
  375.       bufsize = size;
  376.     if(Seek(fh, pos, OFFSET_BEGINNING) < 0)
  377.       ++stop;
  378.     else if(Read(fh, buf, bufsize) != bufsize)
  379.       ++stop;
  380.     for(i = 0; i <= bufsize-7 && !stop; ++i)
  381.     {
  382.       if(buf[i] == 'R' && buf[i+1] == 'a' && buf[i+2] == 'r' && buf[i+3] == '!' &&
  383.       buf[i+4] == 0x1A && buf[i+5] == 7 && buf[i+6] == 0)
  384.       {
  385.         if(Seek(fh, -i, OFFSET_CURRENT) >= 0)
  386.           start = pos+i;
  387.         ++stop;
  388.       }
  389.     }
  390.     size -= i;
  391.     pos += i;
  392.   }
  393.  
  394.   if(start)
  395.     Seek(fh, start, OFFSET_BEGINNING);
  396.   ((ULONG *)buf)[0] = start;
  397.  
  398.   return (BOOL) (start ? TRUE : FALSE);
  399. }
  400.  
  401. /******** exe2cab *********/
  402.  
  403. BOOL ScanCAB(BPTR fh, STRPTR buf, ULONG size, ULONG bufsize)
  404. {
  405.   ULONG start = 0, len = 0, foff;
  406.   LONG i, pos = 0, stop = 0;
  407.  
  408.   while(size > 20 && !stop)
  409.   {
  410.     if(bufsize > size)
  411.       bufsize = size;
  412.     if(Seek(fh, pos, OFFSET_BEGINNING) < 0)
  413.       ++stop;
  414.     else if(Read(fh, buf, bufsize) != bufsize)
  415.       ++stop;
  416.     for(i = 0; i <= bufsize-20 && !stop; ++i)
  417.     {
  418.       if(buf[i] == 'M' && buf[i+1] == 'S' && buf[i+2] == 'C' && buf[i+3] == 'F')
  419.       {
  420.         len = (buf[i+8]) | (buf[i+9]<<8) | (buf[i+10]<<16) | (buf[i+11]<<24);
  421.         foff = (buf[i+16]) | (buf[i+17]<<8) | (buf[i+18]<<16) | (buf[i+19]<<24);
  422.         if(len <= size-i && foff < len)
  423.         {
  424.           if(Seek(fh, -i, OFFSET_CURRENT) >= 0)
  425.             start = pos+i;
  426.           ++stop;
  427.         }
  428.       }
  429.     }
  430.     size -= i;
  431.     pos += i;
  432.   }
  433.  
  434.   if(start)
  435.     Seek(fh, start, OFFSET_BEGINNING);
  436.   ((ULONG *)buf)[0] = len;
  437.  
  438.   return (BOOL) (start ? TRUE : FALSE);
  439. }
  440.  
  441. ULONG ExtractCAB(BPTR infh, BPTR outfh, STRPTR buf, ULONG filesize, ULONG buffersize)
  442. {
  443.   LONG ret;
  444.  
  445.   ret = DoCopy(infh, outfh, buf, (filesize = ((ULONG *)buf)[0]), buffersize);
  446.   
  447.   return ret ? 0 : filesize;
  448. }
  449.  
  450. /******** exe2arj *********/
  451.  
  452. BOOL ScanARJ(BPTR fh, STRPTR buf, ULONG size, ULONG bufsize)
  453. {
  454.   ULONG start = 0, len, cbuf[256], j, k, l;
  455.   LONG i, pos = 0, stop = 0;
  456.   STRPTR mem;
  457.  
  458.   while(size > 50 && !stop)
  459.   {
  460.     if(bufsize > size)
  461.       bufsize = size;
  462.     if(Seek(fh, pos, OFFSET_BEGINNING) < 0)
  463.       ++stop;
  464.     else if(Read(fh, buf, bufsize) != bufsize)
  465.       ++stop;
  466.     for(i = 0; i <= bufsize-50 && !stop; ++i)
  467.     {
  468.       if(buf[i] == 0x60 && buf[i+1] == 0xEA)
  469.       {
  470.         len = (buf[i+2]) | (buf[i+3]<<8);
  471.         if(size-i > len+4)
  472.         {
  473.           if(bufsize-i < len+4)
  474.             break;
  475.           else
  476.           {
  477.             for(l = 0; l < 256; ++l)
  478.             {
  479.               k = l;
  480.  
  481.               for(j = 0; j < 8; ++j)
  482.               {
  483.                 if(k & 1)
  484.                   k = (k >> 1) ^ 0xEDB88320;
  485.                 else
  486.                   k >>= 1;
  487.               }
  488.               cbuf[l] = k;
  489.             }
  490.             l = ~0;
  491.             k = len;
  492.             mem = buf+i+4;
  493.  
  494.             while(k--)
  495.               l = cbuf[(l ^ *mem++) & 0xFF] ^ (l >> 8);
  496.             if(~l == ((mem[0]) | (mem[1]<<8) | (mem[2]<<16) | (mem[3]<<24)))
  497.             {
  498.               if(Seek(fh, -i, OFFSET_CURRENT) >= 0)
  499.                 start = pos+i;
  500.               ++stop;
  501.             }
  502.           }
  503.         }
  504.       }
  505.     }
  506.     size -= i;
  507.     pos += i;
  508.   }
  509.  
  510.   if(start)
  511.     Seek(fh, start, OFFSET_BEGINNING);
  512.   ((ULONG *)buf)[0] = start;
  513.  
  514.   return (BOOL) (start ? TRUE : FALSE);
  515. }
  516.  
  517. /******** exe2lha *********/
  518.  
  519. BOOL ScanLHA(BPTR fh, STRPTR buf, ULONG size, ULONG bufsize)
  520. {
  521.   ULONG start = 0;
  522.  
  523.   if(Read(fh, buf, 100) < 0)
  524.     return 0;
  525.   if(!buf[0] && !buf[1] && buf[2] == 3 && buf[3] == 0xF3 && buf[44] == 'S'
  526.   && buf[45] == 'F' && buf[46] == 'X' && buf[47] == '!')
  527.   {
  528.     start = (buf[55]) | (buf[54]<<8) | (buf[53]<<16) | (buf[52]<<24);
  529.     if(Seek(fh, start, OFFSET_BEGINNING) < 0)
  530.       start = 0;
  531.   }
  532.  
  533.   if(start)
  534.     Seek(fh, start, OFFSET_BEGINNING);
  535.   ((ULONG *)buf)[0] = start;
  536.  
  537.   return (BOOL) (start ? TRUE : FALSE);
  538. }
  539.  
  540. /******** exe2lzh *********/
  541.  
  542. BOOL ScanLZH(BPTR fh, STRPTR buf, ULONG size, ULONG bufsize)
  543. {
  544.   ULONG start = 0;
  545.   LONG i, pos = 0, stop = 0;
  546.  
  547.   while(size > 21 && !stop)
  548.   {
  549.     if(bufsize > size)
  550.       bufsize = size;
  551.     if(Seek(fh, pos, OFFSET_BEGINNING) < 0)
  552.       ++stop;
  553.     else if(Read(fh, buf, bufsize) != bufsize)
  554.       ++stop;
  555.     for(i = 0; i <= bufsize-21 && !stop; ++i)
  556.     {
  557.       if(buf[i+2] == '-' && buf[i+3] == 'l' && (buf[i+4] == 'h' || buf[i+4] == 'z') &&
  558.       buf[i+6] == '-' && buf[20] <= 2)
  559.       {
  560.         if(Seek(fh, -i, OFFSET_CURRENT) >= 0)
  561.           start = pos+i;
  562.         ++stop;
  563.       }
  564.     }
  565.     size -= i;
  566.     pos += i;
  567.   }
  568.  
  569.   if(start)
  570.     Seek(fh, start, OFFSET_BEGINNING);
  571.   ((ULONG *)buf)[0] = start;
  572.  
  573.   return (BOOL) (start ? TRUE : FALSE);
  574. }
  575.  
  576. /**************************/
  577.  
  578. struct ScanData ScanFuncs[] = {
  579. {ScanZIP, ExtractZIP, "zip", "Zip"},
  580. {ScanACE, ExtractACE, "ace", "Ace"},
  581. {ScanRAR, ExtractACE, "rar", "Rar"}, /* reuse ExtractACE */
  582. {ScanCAB, ExtractCAB, "cab", "Cabinet"},
  583. {ScanARJ, ExtractACE, "arj", "Arj"}, /* reuse ExtractACE */
  584. {ScanLHA, ExtractACE, "lha", "LhA"}, /* reuse ExtractACE */
  585. {ScanLZH, ExtractACE, "lzh", "LhA"}, /* reuse ExtractACE */
  586. {0,0},
  587. };
  588.  
  589.