1 /**
2  * @namespace   biew_plugins_auto
3  * @file        plugins/bin/mz.c
4  * @brief       This file contains implementation of MZ file format.
5  * @version     -
6  * @remark      this source file is part of Binary vIEW project (BIEW).
7  *              The Binary vIEW (BIEW) is copyright (C) 1995 Nickols_K.
8  *              All rights reserved. This software is redistributable under the
9  *              licence given in the file "Licence.en" ("Licence.ru" in russian
10  *              translation) distributed in the BIEW archive.
11  * @note        Requires POSIX compatible development system
12  *
13  * @author      Nickols_K
14  * @since       1995
15  * @note        Development, fixes and improvements
16 **/
17 #include <limits.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include <stddef.h>
21 
22 #include "bconsole.h"
23 #include "bmfile.h"
24 #include "biewhelp.h"
25 #include "bin_util.h"
26 #include "colorset.h"
27 #include "codeguid.h"
28 #include "reg_form.h"
29 #include "tstrings.h"
30 #include "biewlib/kbd_code.h"
31 #include "biewlib/pmalloc.h"
32 #include "plugins/disasm.h"
33 #include "plugins/bin/mz.h"
34 
35 static MZHEADER mz;
36 static unsigned long HeadSize;
37 
mzVA2PA(__filesize_t va)38 static __filesize_t __FASTCALL__ mzVA2PA(__filesize_t va)
39 {
40   return va >= HeadSize ? va + HeadSize : 0L;
41 }
42 
mzPA2VA(__filesize_t pa)43 static __filesize_t __FASTCALL__ mzPA2VA(__filesize_t pa)
44 {
45   return pa >= HeadSize ? pa - HeadSize : 0L;
46 }
47 
__QueryAddInfo(unsigned char * memmap)48 static const char * __NEAR__ __FASTCALL__ __QueryAddInfo( unsigned char *memmap )
49 {
50   static char rbuff[41];
51   unsigned long idl;
52   unsigned short idw,idw0;
53   idl = ((unsigned long *)memmap)[0];
54   idw0 = ((unsigned short *)memmap)[0];
55   idw = ((unsigned short *)memmap)[2];
56   if(memcmp(memmap,"RJSX",4) == 0) { ArjARC: return "ARJ self-extracting archive"; }
57   else
58     if(memcmp(memmap,"LZ09",4) == 0) return "LZEXE 0.90 compressed executable";
59     else
60       if(memcmp(memmap,"LZ91",4) == 0) return "LZEXE 0.91 compressed executable";
61       else
62         if(memmap[2] == 0xFB)
63         {
64            char hi,low;
65            hi = (memmap[3] >> 4) & 0x0F;
66            low = memmap[3] & 0x0F;
67            sprintf(rbuff,"Borland TLINK version: %u.%u",(unsigned)hi,(unsigned)low);
68            return rbuff;
69         }
70         else
71           if(memcmp(&memmap[2],"PKLITE",6) == 0)
72           {
73              char hi, low;
74              low = memmap[0];
75              hi =  memmap[1] & 0x0F;
76              sprintf(rbuff,"PKLITE v%u.%u compressed executable",(unsigned)hi,(unsigned)low);
77              return rbuff;
78           }
79           else
80             if(memcmp(&memmap[9],"LHarc's SFX",11) == 0) return "LHarc 1.x self-extracting archive";
81             else
82               if(memcmp(&memmap[8],"LHa's SFX",9) == 0) return "LHa 2.x self-extracting archive";
83               else
84                 if(idl == 0x018A0001L && idw == 0x1565) return "TopSpeed 3.0 CRUNCH compressed file";
85                 else
86                   if(idl == 0x00020001L && idw == 0x0700) return "PKARCK 3.5 self-extracting-archive";
87                   else
88                     if(idw0 == 0x000F && memmap[2] == 0xA7) return "BSA (Soviet archiver) selft-extarcting";
89                     else
90                       if(memcmp(&memmap[4],"SFX by LARC",11) == 0) return "LARC self-extracting archive";
91                       else
92                         if(memcmp(&memmap[8],"LH's SFX",8) == 0) return "LH self-extracting archive";
93                         else
94                         {
95                           unsigned i;
96                           for(i = 0;i < 1000-6;i++)
97                           {
98                             if(memmap[i] == 'a' && memcmp(&memmap[i+1],"RJsfX",5) == 0)
99                             {
100                                goto ArjARC;
101                             }
102                           }
103                         }
104  return 0;
105 }
106 
QueryAddInfo(void)107 static const char * __NEAR__ __FASTCALL__ QueryAddInfo( void )
108 {
109    unsigned char *memmap;
110    memmap = PMalloc(1000);
111    if(memmap)
112    {
113      const char *ret;
114      __filesize_t fpos;
115      fpos = bmGetCurrFilePos();
116      bmReadBufferEx(memmap,1000,0x1C,BM_SEEK_SET);
117      bmSeek(fpos,BM_SEEK_SET);
118      ret = __QueryAddInfo(memmap);
119      PFREE(memmap);
120      return ret;
121    }
122    return NULL;
123 }
124 
ShowMZHeader(void)125 static __filesize_t __FASTCALL__ ShowMZHeader( void )
126 {
127  unsigned keycode;
128  TWindow * hwnd;
129  __filesize_t newcpos,fpos;
130  unsigned long FPageCnt;
131  const char * addinfo;
132  fpos = BMGetCurrFilePos();
133  keycode = 16;
134  if(IsNewExe()) keycode++;
135  addinfo = QueryAddInfo();
136  if(addinfo) keycode++;
137  hwnd = CrtDlgWndnls(" Old Exe Header ",43,keycode-1);
138  FPageCnt =  ((long)mz.mzPageCount - 1)*512;
139  twUseWin(hwnd);
140  twGotoXY(1,1);
141  twPrintF("Signature            = 'MZ'\n"
142           "Part Last Page       = %hu [ bytes ]\n"
143           "Page count           = %hu [ pages ]\n"
144           "Relocations count    = %hu\n"
145           "Header size          = %hu [ paragraphs ]\n"
146           "Minimum memory       = %04hXH [ paragraphs ]\n"
147           "Maximum memory       = %04hXH [ paragraphs ]\n"
148           "SS : SP              = %04hX:%04hXH\n"
149           "Check summ           = %hu\n"
150           "CS : IP              = %04hX:%04hXH\n"
151           "Table offset         = %04hXH [ bytes ]\n"
152           "Overlay Number       = %hu\n"
153           ,mz.mzPartLastPage
154           ,mz.mzPageCount
155           ,mz.mzRelocationCount
156           ,mz.mzHeaderSize
157           ,mz.mzMinMem
158           ,mz.mzMaxMem
159           ,mz.mzRelocationSS,mz.mzExeSP
160           ,mz.mzCheckSumm
161           ,mz.mzRelocationCS,mz.mzExeIP
162           ,mz.mzTableOffset
163           ,mz.mzOverlayNumber);
164  newcpos = HeadSize;
165  newcpos += (((unsigned long)mz.mzRelocationCS) << 4) + (unsigned long)mz.mzExeIP;
166  twSetColorAttr(dialog_cset.entry);
167  twPrintF(">Entry Point         = %08lXH",newcpos); twClrEOL();
168  twSetColorAttr(dialog_cset.addinfo);
169  twPrintF("\nModule Length        = %lu [ bytes ]",(FPageCnt - HeadSize) + mz.mzPartLastPage);
170  twClrEOL();
171  twSetColorAttr(dialog_cset.main);
172  twPrintF("\nImage offset         = %08lXH",(long)HeadSize);
173  if(headshift)
174  {
175    twSetColorAttr(dialog_cset.altinfo);
176    twPrintF("\nNew EXE header shift = %08lXH",(long)headshift);
177    twClrEOL();
178  }
179  if(addinfo)
180  {
181    twSetColorAttr(dialog_cset.extrainfo);
182    twPrintF("\n%s",addinfo);
183    twClrEOL();
184  }
185  while(1)
186  {
187    keycode = GetEvent(drawEmptyPrompt,NULL,hwnd);
188    if(keycode == KE_F(5) || keycode == KE_ENTER) { fpos = newcpos; break; }
189    else
190      if(keycode == KE_ESCAPE || keycode == KE_F(10)) break;
191  }
192  CloseWnd(hwnd);
193  return fpos;
194 }
195 
196 long __HUGE__ * CurrMZChain = 0;
197 static unsigned long CurrMZCount;
198 static char __codelen;
199 
compare_ptr(const void __HUGE__ * e1,const void __HUGE__ * e2)200 static tCompare __FASTCALL__ compare_ptr(const void __HUGE__ *e1,const void __HUGE__ *e2)
201 {
202   unsigned long v1,v2;
203   v1 = *((const unsigned long __HUGE__ *)e1);
204   v2 = *((const unsigned long __HUGE__ *)e2);
205   return __CmpLong__(v1,v2);
206 }
207 
BuildMZChain(void)208 static void __NEAR__ __FASTCALL__ BuildMZChain( void )
209 {
210   unsigned i;
211   __filesize_t fpos;
212   TWindow * w,*usd;
213   usd = twUsedWin();
214   w = CrtDlgWndnls(SYSTEM_BUSY,49,1);
215   twUseWin(w);
216   twGotoXY(1,1);
217   twPutS(BUILD_REFS);
218   twUseWin(usd);
219   CurrMZCount = 0;
220   fpos = bmGetCurrFilePos();
221   for(i = 0;i < mz.mzRelocationCount;i++)
222   {
223     unsigned off,seg,j;
224     __filesize_t ptr;
225     void __HUGE__ * tptr;
226     if(!CurrMZChain) tptr = PHMalloc(sizeof(void *));
227     else             tptr = PHRealloc(CurrMZChain,(CurrMZCount + 1)*sizeof(void *));
228     if(!tptr) break;
229     CurrMZChain = tptr;
230     j = mz.mzTableOffset + i*4;
231     bmSeek(j,BM_SEEK_SET);
232     off = bmReadWord();
233     seg = bmReadWord();
234     ptr = (((long)seg) << 4) + off + (((long)mz.mzHeaderSize) << 4);
235     CurrMZChain[CurrMZCount++] = ptr;
236   }
237   HQSort(CurrMZChain,CurrMZCount,sizeof(void *),compare_ptr);
238   bmSeek(fpos,BM_SEEK_SET);
239   CloseWnd(w);
240 }
241 
compare_mz(const void __HUGE__ * e1,const void __HUGE__ * e2)242 static tCompare __FASTCALL__ compare_mz(const void __HUGE__ *e1,const void __HUGE__ *e2)
243 {
244   long l1,l2;
245   tCompare ret;
246   l1 = *(const long __HUGE__ *)e1;
247   l2 = *(const long __HUGE__ *)e2;
248   if(l1 >= l2 && l1 < l2 + __codelen) ret = 0;
249   else
250     if(l1 < l2) ret = -1;
251     else        ret = 1;
252   return ret;
253 }
254 
isMZReferenced(__filesize_t shift,char len)255 static tBool __NEAR__ __FASTCALL__ isMZReferenced(__filesize_t shift,char len)
256 {
257   if(mz.mzRelocationCount)
258   {
259      __filesize_t mz_size;
260      mz_size = (long)(mz.mzPageCount)*512 + mz.mzPartLastPage;
261      if(shift <= mz_size && shift >= ((unsigned long)mz.mzHeaderSize) << 4)
262      {
263        if(!CurrMZChain) BuildMZChain();
264        __codelen = len;
265        return HLFind(&shift,CurrMZChain,CurrMZCount,sizeof(long),compare_mz) != 0;
266      }
267   }
268   return False;
269 }
AppendMZRef(char * str,__filesize_t ulShift,int flags,int codelen,__filesize_t r_sh)270 static unsigned long __FASTCALL__ AppendMZRef(char *str,__filesize_t ulShift,int flags,int codelen,__filesize_t r_sh)
271 {
272   char stmp[256];
273   unsigned long ret = RAPREF_NONE;
274   if(flags & APREF_TRY_PIC) return RAPREF_NONE;
275   if(isMZReferenced(ulShift,codelen))
276   {
277      unsigned wrd;
278      wrd = bmReadWordEx(ulShift,BM_SEEK_SET);
279      strcat(str,Get4Digit(wrd));
280      strcat(str,"+PID");
281      ret = RAPREF_DONE;
282   }
283   if(!DumpMode && !EditMode && (flags & APREF_TRY_LABEL) && codelen == 4)
284   {
285     r_sh += (((__filesize_t)mz.mzHeaderSize) << 4);
286     if(udnFindName(r_sh,stmp,sizeof(stmp))==True) strcat(str,stmp);
287     else strcat(str,Get8Digit(r_sh));
288     GidAddGoAddress(str,r_sh);
289     ret = RAPREF_DONE;
290   }
291   return ret;
292 }
293 
mz_check_fmt(void)294 static tBool  __FASTCALL__ mz_check_fmt( void )
295 {
296   unsigned char id[2];
297   tBool ret = False;
298   bmReadBufferEx(id,sizeof(id),0,BM_SEEK_SET);
299   if((id[0] == 'M' && id[1] == 'Z') ||
300      (id[0] == 'Z' && id[1] == 'M'))
301   {
302     bmReadBufferEx((void  *)&mz,sizeof(MZHEADER),2,BM_SEEK_SET);
303     HeadSize = ((unsigned long)mz.mzHeaderSize) << 4;
304     ret = True;
305   }
306   return ret;
307 }
308 
309 /* Special case: this module must not use init and destroy */
mz_init_fmt(void)310 static void __FASTCALL__ mz_init_fmt( void ) {}
mz_destroy_fmt(void)311 static void __FASTCALL__ mz_destroy_fmt(void) {}
mz_platform(void)312 static int  __FASTCALL__ mz_platform( void) { return DISASM_CPU_IX86; }
313 
mzAddressResolv(char * addr,__filesize_t cfpos)314 static tBool __FASTCALL__ mzAddressResolv(char *addr,__filesize_t cfpos)
315 {
316   tBool bret = True;
317   if(cfpos < sizeof(MZHEADER)+2) sprintf(addr,"MZH :%s",Get4Digit(cfpos));
318   else
319     if(cfpos >= sizeof(MZHEADER)+2 && cfpos < sizeof(MZHEADER)+2+(mz.mzRelocationCount<<2))
320     {
321       sprintf(addr,"MZRl:%s",Get4Digit(cfpos - sizeof(MZHEADER)));
322     }
323     else
324      if(cfpos >= HeadSize)
325      {
326        addr[0] = '.';
327        strcpy(&addr[1],Get8Digit(mzPA2VA(cfpos)));
328      }
329      else bret = False;
330   return bret;
331 }
332 
MZHelp(void)333 static __filesize_t __FASTCALL__ MZHelp( void )
334 {
335   hlpDisplay(10013);
336   return BMGetCurrFilePos();
337 }
338 
339 REGISTRY_BIN mzTable =
340 {
341   "MZ (Old DOS-exe)",
342   { "MZHelp", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
343   { MZHelp, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
344   mz_check_fmt,
345   mz_init_fmt,
346   mz_destroy_fmt,
347   ShowMZHeader,
348   AppendMZRef,
349   NULL,
350   mz_platform,
351   NULL,
352   NULL,
353   mzAddressResolv,
354   mzVA2PA,
355   mzPA2VA,
356   NULL,
357   NULL,
358   NULL,
359   NULL
360 };
361