home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / FILE / UNLZEXE7.ZIP / UNLZEXE7.C next >
Encoding:
C/C++ Source or Header  |  1991-11-21  |  12.4 KB  |  457 lines

  1. /* unlzexe.c */
  2. #define VERSION "0.7"
  3.  
  4. /* unlzexe ver 0.5 (PC-VAN UTJ44266 Kou )
  5. *   UNLZEXE converts the compressed file by lzexe(ver.0.90,0.91) to the
  6. *   UNcompressed executable one.
  7. *
  8. *   usage:  UNLZEXE packedfile[.EXE] [unpackedfile.EXE]
  9.  
  10. v0.6  David Kirschbaum, Toad Hall, kirsch@usasoc.soc.mil, Jul 91
  11.     Problem reported by T.Salmi (ts@uwasa.fi) with UNLZEXE when run
  12.     with TLB-V119 on 386's.
  13.     Stripping out the iskanji and isjapan() stuff (which uses a somewhat
  14.     unusual DOS interrupt) to see if that's what's biting us.
  15.  
  16. --  Found it, thanks to Dan Lewis (DLEWIS@SCUACC.SCU.EDU).
  17.     Silly us:  didn't notice the "r.h.al=0x3800;" in isjapan().
  18.     Oh, you don't see it either?  INT functions are called with AH
  19.     having the service.  Changing to "r.x.ax=0x3800;".
  20.  
  21. v0.7  Alan Modra, amodra@sirius.ucs.adelaide.edu.au, Nov 91
  22.     Fixed problem with large files by casting ihead components to long
  23.     in various expressions.
  24.     Fixed MinBSS & MaxBSS calculation (ohead[5], ohead[6]).  Now UNLZEXE
  25.     followed by LZEXE should give the original file.
  26. */
  27.  
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <dos.h>
  32. #ifdef __TURBOC__
  33. #include <dir.h>
  34. /*
  35. #define MAXPATH   80
  36. #define MAXDRIVE  3
  37. #define MAXDIR    66
  38. #define MAXFILE   9
  39. #define MAXEXT    5
  40. #define FILENAME_MAX MAXPATH
  41. */
  42. #endif
  43.  
  44. #define FAILURE 1
  45. #define SUCCESS 0
  46.  
  47. typedef unsigned int WORD;
  48. typedef unsigned char BYTE;
  49.  
  50. int isjapan(void);
  51. int japan_f;
  52. #define    iskanji(c)    ('\x81'<=(c)&&(c)<='\x9f' || '\xe0'<=(c)&&(c)<='\xfc')
  53.  
  54. char *tmpfname = "$tmpfil$.exe";
  55. char *backup_ext = ".olz";
  56. char ipath[FILENAME_MAX],
  57.      opath[FILENAME_MAX],
  58.      ofname[13];
  59.  
  60. #ifdef __TURBOC__
  61. /* I like prototypes */
  62. int reloc90(FILE *ifile,FILE *ofile,long fpos);
  63. int reloc91(FILE *ifile,FILE *ofile,long fpos);
  64. #endif
  65.  
  66. void main(int argc,char **argv){
  67.     int fnamechk(char*,char*,char*,int,char**);
  68.     int fnamechg(char*,char*,char*,int);
  69.     int rdhead(FILE *,int *);
  70.     int mkreltbl(FILE *,FILE *,int);
  71.     int unpack(FILE *,FILE *);
  72.     void wrhead(FILE *);
  73.  
  74.     FILE *ifile,*ofile;
  75.     int  ver,rename_sw=0;
  76.  
  77.     printf("UNLZEXE Ver. "VERSION"\n");        /* v0.6 */
  78.     japan_f=isjapan();
  79.     if(argc!=3 && argc!=2){
  80.         printf("usage: UNLZEXE packedfile [unpackedfile]\n");
  81.         exit(EXIT_FAILURE);
  82.     }
  83.     if(argc==2)
  84.         rename_sw=1;
  85.     if(fnamechk(ipath,opath,ofname,argc,argv)!=SUCCESS) {
  86.         exit(EXIT_FAILURE);
  87.     }
  88.     if((ifile=fopen(ipath,"rb"))==NULL){
  89.         printf("'%s' :not found\n",ipath);
  90.             exit(EXIT_FAILURE);
  91.     }
  92.  
  93.     if(rdhead(ifile,&ver)!=SUCCESS){
  94.         printf("'%s' is not LZEXE file.\n",ipath);
  95.         fclose(ifile); exit(EXIT_FAILURE);
  96.     }
  97.     if((ofile=fopen(opath,"w+b"))==NULL){
  98.         printf("can't open '%s'.\n",opath);
  99.         fclose(ifile); exit(EXIT_FAILURE);
  100.     }
  101.     printf("file '%s' is compressed by LZEXE Ver. ",ipath);
  102.     switch(ver){
  103.     case 90: printf("0.90\n"); break;
  104.     case 91: printf("0.91\n"); break;
  105.     }
  106.     if(mkreltbl(ifile,ofile,ver)!=SUCCESS) {
  107.         fclose(ifile);
  108.         fclose(ofile);
  109.         remove(opath);
  110.         exit(EXIT_FAILURE);
  111.     }
  112.     if(unpack(ifile,ofile)!=SUCCESS) {
  113.         fclose(ifile);
  114.         fclose(ofile);
  115.         remove(opath);
  116.         exit(EXIT_FAILURE);
  117.     }
  118.     fclose(ifile);
  119.     wrhead(ofile);
  120.     fclose(ofile);
  121.  
  122.     if(fnamechg(ipath,opath,ofname,rename_sw)!=SUCCESS){
  123.         exit(EXIT_FAILURE);
  124.     }
  125.     exit(EXIT_SUCCESS);
  126. }
  127.  
  128.  
  129.  
  130. void parsepath(char *pathname, int *fname, int *ext);
  131.  
  132. /* file name check */
  133. int fnamechk(char *ipath,char *opath, char *ofname,
  134.               int argc,char **argv) {
  135.     int idx_name,idx_ext;
  136.  
  137.     strcpy(ipath,argv[1]);
  138.     parsepath(ipath,&idx_name,&idx_ext);
  139.     if (! ipath[idx_ext]) strcpy(ipath+idx_ext,".exe");
  140.     if(! stricmp(ipath+idx_name,tmpfname)){
  141.         printf("'%s':bad filename.\n",ipath);
  142.         return(FAILURE);
  143.     }
  144.     if(argc==2)
  145.         strcpy(opath,ipath);
  146.     else
  147.         strcpy(opath,argv[2]);
  148.     parsepath(opath,&idx_name,&idx_ext);
  149.     if (! opath[idx_ext]) strcpy(opath+idx_ext,".exe");
  150.     if (!stricmp(opath+idx_ext,backup_ext)){
  151.         printf("'%s':bad filename.\n",opath);
  152.         return(FAILURE);
  153.     }
  154.     strncpy(ofname,opath+idx_name,12);
  155.     strcpy(opath+idx_name,tmpfname);
  156.     return(SUCCESS);
  157. }
  158.  
  159.  
  160. int fnamechg(char *ipath,char *opath,char *ofname,int rename_sw) {
  161.     int idx_name,idx_ext;
  162.     char tpath[FILENAME_MAX];
  163.  
  164.     if(rename_sw) {
  165.         strcpy(tpath,ipath);
  166.         parsepath(tpath,&idx_name,&idx_ext);
  167.         strcpy(tpath+idx_ext,backup_ext);
  168.         remove(tpath);
  169.         if(rename(ipath,tpath)){
  170.             printf("can't make '%s'.\n", tpath);
  171.             remove(opath);
  172.             return(FAILURE);
  173.         }
  174.     printf("'%s' is renamed to '%s'.\n",ipath,tpath);
  175.     }
  176.     strcpy(tpath,opath);
  177.     parsepath(tpath,&idx_name,&idx_ext);
  178.     strcpy(tpath+idx_name,ofname);
  179.     remove(tpath);
  180.     if(rename(opath,tpath)){
  181.         if(rename_sw) {
  182.             strcpy(tpath,ipath);
  183.             parsepath(tpath,&idx_name,&idx_ext);
  184.             strcpy(tpath+idx_ext,backup_ext);
  185.             rename(tpath,ipath);
  186.         }
  187.         printf("can't make '%s'.  unpacked file '%s' is remained.\n",
  188.                  tpath, tmpfname);
  189.  
  190.         return(FAILURE);
  191.     }
  192.     printf("unpacked file '%s' is generated.\n",tpath);
  193.     return(SUCCESS);
  194. }
  195.  
  196. int isjapan() {
  197.     union REGS r;
  198.     struct SREGS rs;
  199.     BYTE buf[34];
  200.  
  201.     segread(&rs);
  202.     rs.ds=rs.ss;  r.x.dx=(WORD)buf;
  203. /*    r.h.al=0x3800; v0.6 */
  204.     r.x.ax=0x3800;        /* svc 38H, check for country v0.6 */
  205.     intdosx(&r,&r,&rs);
  206.     return(!strcmp(buf+2,"\\"));
  207. }
  208.  
  209. void parsepath(char *pathname, int *fname, int *ext) {
  210.     /* use  int japan_f */
  211.     char c;
  212.     int i;
  213.  
  214.     *fname=0; *ext=0;
  215.     for(i=0;c=pathname[i];i++) {
  216.         if(japan_f && iskanji(c))
  217.             i++;
  218.         else
  219.             switch(c) {
  220.             case ':' :
  221.             case '\\':  *fname=i+1; break;
  222.             case '.' :  *ext=i; break;
  223.             default  :  ;
  224.             }
  225.     }
  226.     if(*ext<=*fname) *ext=i;
  227. }
  228. /*-------------------------------------------*/
  229. static WORD ihead[0x10],ohead[0x10],inf[8];
  230. static long loadsize;
  231.  
  232. /* EXE header test (is it LZEXE file?) */
  233. int rdhead(FILE *ifile ,int *ver){
  234.     if(fread(ihead,sizeof ihead[0],0x10,ifile)!=0x10)
  235.         return FAILURE;
  236.     memcpy(ohead,ihead,sizeof ihead[0] * 0x10);
  237.     if(ihead[0]!=0x5a4d || ihead[4]!=2 || ihead[0x0d]!=0)
  238.         return FAILURE;
  239.     if(ihead[0x0c]==0x1c && memcmp(&ihead[0x0e],"LZ09",4)==0){
  240.         *ver=90; return SUCCESS ;
  241.     }
  242.     if(ihead[0x0c]==0x1c && memcmp(&ihead[0x0e],"LZ91",4)==0){
  243.         *ver=91; return SUCCESS ;
  244.     }
  245.     return FAILURE;
  246. }
  247.  
  248. /* make relocation table */
  249. int mkreltbl(FILE *ifile,FILE *ofile,int ver) {
  250.     int reloc90();
  251.     int reloc91();
  252.     long fpos;
  253.     int i;
  254.  
  255. /* v0.7 old code
  256.  *  allocsize=((ihead[1]+16-1)>>4) + ((ihead[2]-1)<<5) - ihead[4] + ihead[5];
  257.  */
  258.     fpos=(long)(ihead[0x0b]+ihead[4])<<4;        /* goto CS:0000 */
  259.     fseek(ifile,fpos,SEEK_SET);
  260.     fread(inf, sizeof inf[0], 0x08, ifile);
  261.     ohead[0x0a]=inf[0];        /* IP */
  262.     ohead[0x0b]=inf[1];        /* CS */
  263.     ohead[0x08]=inf[2];        /* SP */
  264.     ohead[0x07]=inf[3];        /* SS */
  265.     /* inf[4]:size of compressed load module (PARAGRAPH)*/
  266.     /* inf[5]:increase of load module size (PARAGRAPH)*/
  267.     /* inf[6]:size of decompressor with  compressed relocation table (BYTE) */
  268.     /* inf[7]:check sum of decompresser with compressd relocation table(Ver.0.90) */
  269.     ohead[0x0c]=0x1c;        /* start position of relocation table */
  270.     fseek(ofile,0x1cL,SEEK_SET);
  271.     switch(ver){
  272.     case 90: i=reloc90(ifile,ofile,fpos);
  273.              break;
  274.     case 91: i=reloc91(ifile,ofile,fpos);
  275.              break;
  276.     default: i=FAILURE; break;
  277.     }
  278.     if(i!=SUCCESS){
  279.         printf("error at relocation table.\n");
  280.         return (FAILURE);
  281.     }
  282.   
  283.     fpos=ftell(ofile);
  284. /* v0.7 old code
  285.  *  i= (int) fpos & 0x1ff;
  286.  *  if(i) i=0x200-i;
  287.  *  ohead[4]= (int) (fpos+i)>>4;
  288.  */
  289.     i= (0x200 - (int) fpos) & 0x1ff;    /* v0.7 */
  290.     ohead[4]= (int) ((fpos+i)>>4);    /* v0.7 */
  291.  
  292.     for( ; i>0; i--)
  293.         putc(0, ofile);
  294.     return(SUCCESS);
  295. }
  296. /* for LZEXE ver 0.90 */
  297. int reloc90(FILE *ifile,FILE *ofile,long fpos) {
  298.     unsigned int c;
  299.     WORD rel_count=0;
  300.     WORD rel_seg,rel_off;
  301.  
  302.     fseek(ifile,fpos+0x19d,SEEK_SET);
  303.                     /* 0x19d=compressed relocation table address */
  304.     rel_seg=0;
  305.     do{
  306.         if(feof(ifile) || ferror(ifile) || ferror(ofile)) return(FAILURE);
  307.         c=getw(ifile);
  308.         for(;c>0;c--) {
  309.             rel_off=getw(ifile);
  310.             putw(rel_off,ofile);
  311.             putw(rel_seg,ofile);
  312.             rel_count++;
  313.         }
  314.         rel_seg += 0x1000;
  315.     } while(rel_seg!=(0xf000+0x1000));
  316.     ohead[3]=rel_count;
  317.     return(SUCCESS);
  318. }
  319. /* for LZEXE ver 0.91*/
  320. int reloc91(FILE *ifile,FILE *ofile,long fpos) {
  321.     WORD span;
  322.     WORD rel_count=0;
  323.     WORD rel_seg,rel_off;
  324.  
  325.     fseek(ifile,fpos+0x158,SEEK_SET);
  326.                     /* 0x158=compressed relocation table address */
  327.     rel_off=0; rel_seg=0;
  328.     for(;;) {
  329.         if(feof(ifile) || ferror(ifile) || ferror(ofile)) return(FAILURE);
  330.         if((span=getc(ifile))==0) {
  331.             span=getw(ifile);
  332.             if(span==0){
  333.                 rel_seg += 0x0fff;
  334.                 continue;
  335.             } else if(span==1){
  336.                 break;
  337.             }
  338.         }
  339.         rel_off += span;
  340.         rel_seg += (rel_off & ~0x0f)>>4;
  341.         rel_off &= 0x0f;
  342.         putw(rel_off,ofile);
  343.         putw(rel_seg,ofile);
  344.         rel_count++;
  345.     }
  346.     ohead[3]=rel_count;
  347.     return(SUCCESS);
  348. }
  349.  
  350. /*---------------------*/
  351. typedef struct {
  352.         FILE  *fp;
  353.         WORD  buf;
  354.         BYTE  count;
  355.     } bitstream;
  356.  
  357. void initbits(bitstream *,FILE *);
  358. int getbit(bitstream *);
  359.  
  360. /*---------------------*/
  361. /* decompressor routine */
  362. int unpack(FILE *ifile,FILE *ofile){
  363.     int len;
  364.     int span;
  365.     long fpos;
  366.     bitstream bits;
  367.     static BYTE data[0x4500], *p=data;
  368.  
  369.     fpos=((long)ihead[0x0b]-(long)inf[4]+(long)ihead[4])<<4;
  370.     fseek(ifile,fpos,SEEK_SET);
  371.     fpos=(long)ohead[4]<<4;
  372.     fseek(ofile,fpos,SEEK_SET);
  373.     initbits(&bits,ifile);
  374.     printf(" unpacking. ");
  375.     for(;;){
  376.         if(ferror(ifile)) {printf("\nread error\n"); return(FAILURE); }
  377.         if(ferror(ofile)) {printf("\nwrite error\n"); return(FAILURE); }
  378.         if(p-data>0x4000){
  379.             fwrite(data,sizeof data[0],0x2000,ofile);
  380.             p-=0x2000;
  381.             memcpy(data,data+0x2000,p-data);
  382.             putchar('.');
  383.         }
  384.         if(getbit(&bits)) {
  385.             *p++=getc(ifile);
  386.             continue;
  387.         }
  388.         if(!getbit(&bits)) {
  389.             len=getbit(&bits)<<1;
  390.             len |= getbit(&bits);
  391.             len += 2;
  392.             span=getc(ifile) | 0xff00;
  393.         } else {
  394.             span=(BYTE)getc(ifile);
  395.             len=getc(ifile);
  396.             span |= ((len & ~0x07)<<5) | 0xe000;
  397.             len = (len & 0x07)+2;
  398.             if (len==2) {
  399.                 len=getc(ifile);
  400.  
  401.                 if(len==0)
  402.                     break;    /* end mark of compreesed load module */
  403.  
  404.                 if(len==1)
  405.                     continue; /* segment change */
  406.                 else
  407.                     len++;
  408.             }
  409.         }
  410.         for( ;len>0;len--,p++){
  411.             *p=*(p+span);
  412.         }
  413.     }
  414.     if(p!=data)
  415.         fwrite(data,sizeof data[0],p-data,ofile);
  416.     loadsize=ftell(ofile)-fpos;
  417.     printf("end\n");
  418.     return(SUCCESS);
  419. }
  420.  
  421. /* write EXE header*/
  422. void wrhead(FILE *ofile) {
  423.     if(ihead[6]!=0) {
  424.         ohead[5]-= inf[5] + ((inf[6]+16-1)>>4) + 9;    /* v0.7 */
  425.         if(ihead[6]!=0xffff)
  426.             ohead[6]-=(ihead[5]-ohead[5]);
  427.     }
  428.     ohead[1]=((WORD)loadsize+(ohead[4]<<4)) & 0x1ff;    /* v0.7 */
  429.     ohead[2]=(WORD)((loadsize+((long)ohead[4]<<4)+0x1ff) >> 9);    /* v0.7 */
  430.     fseek(ofile,0L,SEEK_SET);
  431.     fwrite(ohead,sizeof ohead[0],0x0e,ofile);
  432. }
  433.  
  434.  
  435. /*-------------------------------------------*/
  436.  
  437. /* get compress information bit by bit */
  438. void initbits(bitstream *p,FILE *filep){
  439.     p->fp=filep;
  440.     p->count=0x10;
  441.     p->buf=getw(filep);
  442.     /* printf("%04x ",p->buf); */
  443. }
  444.  
  445. int getbit(bitstream *p) {
  446.     int b;
  447.     b = p->buf & 1;
  448.     if(--p->count == 0){
  449.         (p->buf)=getw(p->fp);
  450.         /* printf("%04x ",p->buf); */
  451.         p->count= 0x10;
  452.     }else
  453.         p->buf >>= 1;
  454.     
  455.     return b;
  456. }
  457.