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