1 /**
2 * @namespace biew_plugins_auto
3 * @file plugins/bin/ne.c
4 * @brief This file contains implementation of NE (New Executable) file
5 * format decoder.
6 * @version -
7 * @remark this source file is part of Binary vIEW project (BIEW).
8 * The Binary vIEW (BIEW) is copyright (C) 1995 Nickols_K.
9 * All rights reserved. This software is redistributable under the
10 * licence given in the file "Licence.en" ("Licence.ru" in russian
11 * translation) distributed in the BIEW archive.
12 * @note Requires POSIX compatible development system
13 *
14 * @author Nickols_K
15 * @since 1995
16 * @note Development, fixes and improvements
17 **/
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <limits.h>
22
23 #include "colorset.h"
24 #include "plugins/disasm.h"
25 #include "plugins/bin/ne.h"
26 #include "bin_util.h"
27 #include "bmfile.h"
28 #include "biewhelp.h"
29 #include "tstrings.h"
30 #include "biewutil.h"
31 #include "bconsole.h"
32 #include "reg_form.h"
33 #include "codeguid.h"
34 #include "biewlib/pmalloc.h"
35 #include "biewlib/biewlib.h"
36 #include "biewlib/kbd_code.h"
37
38 static NEHEADER ne;
39
40 static BGLOBAL ne_cache = &bNull;
41 static BGLOBAL ne_cache1 = &bNull;
42 static BGLOBAL ne_cache2 = &bNull;
43 static BGLOBAL ne_cache3 = &bNull;
44
45 static __filesize_t __NEAR__ __FASTCALL__ CalcEntryPointNE( unsigned,unsigned );
46 static void __FASTCALL__ ne_ReadPubNameList(BGLOBAL handle,void (__FASTCALL__ *mem_out)(const char *));
47 static tBool __NEAR__ __FASTCALL__ FindPubName(char *buff,unsigned cb_buff,__filesize_t pa);
48 static void __FASTCALL__ rd_ImpName(char *buff,int blen,unsigned idx,tBool useasoff);
49 static __filesize_t __FASTCALL__ nePA2VA(__filesize_t pa);
50
neLowMemFunc(unsigned long need_mem)51 static tBool __FASTCALL__ neLowMemFunc( unsigned long need_mem )
52 {
53 UNUSED(need_mem);
54 if(!fmtActiveState)
55 {
56 if(PubNames)
57 {
58 la_Destroy(PubNames);
59 PubNames = NULL;
60 return True;
61 }
62 }
63 return False;
64 }
65
66 const char * __nedata[] =
67 {
68 "NOAUTODATA",
69 "SINGLEDATA",
70 "MULTIPLEDATA",
71 "(SINGLE & MULTIPLE DATA)"
72 };
73
74 const char * __neExeType[] =
75 {
76 "Unknown (Any)",
77 "OS/2",
78 "Windows",
79 "DOS4",
80 "Windows Dev386"
81 };
82
__getNEType(unsigned type)83 static const char * __FASTCALL__ __getNEType(unsigned type)
84 {
85 if(type > 4) type = 0;
86 return __neExeType[type];
87 }
88
89 const char * PMWinAPI[4] =
90 {
91 "Text or Windowing API not declared.",
92 "(NOTWINDOWCOMPAT). Full screen character-mode application.",
93 "(WINDOWCOMPAT). Text window character mode application.",
94 "(WINDOWAPI). Windowing application."
95 };
96
GetPMWinAPI(unsigned flag)97 const char * __FASTCALL__ GetPMWinAPI(unsigned flag)
98 {
99 flag >>= 8;
100 flag &= 0x0003;
101 return PMWinAPI[flag];
102 }
103
PaintNewHeaderNE_1(void)104 static void __NEAR__ PaintNewHeaderNE_1( void )
105 {
106 twPrintF("Signature = '%c%c'\n"
107 "Linker Version.Revision = %hd.%hd\n"
108 "Offset of Entry Table = %XH\n"
109 "Length of Entry Table = %hu [ bytes ]\n"
110 "< 32-bit Checksum > = %08lXH\n"
111 "NE Flags : = [%04hXH]\n"
112 " Contest DATA in EXE: %s\n"
113 " [%c] < Per-process library initialization (INITINSTANCE) >\n"
114 " [%c] Runs in protected mode only (PROTMODE)\n"
115 " [%c] Win: [LIM 3.2 used fow Windows] OS/2: [8086 instruction]\n"
116 " [%c] Win: [Multi instance EMS memory] OS/2: [80286 instructions]\n"
117 " [%c] Win: [DLL Global memory above EMS] OS/2: [80386 instructions]\n"
118 " [%c] OS/2: Floating point instructrions\n"
119 " %s\n"
120 " [%c] First segment contains code that loads API (Bound Family/API)\n"
121 " [%c] Linker detects errors at link time, but still creates module\n"
122 " [%c] Win: [Module must located in EMS] OS/2: [SMP mode disabled]\n"
123 " [%c] Module is library (DLL)\n"
124 "DS (DGROUP) = %hu\n"
125 "HEAPSIZE = %hu\n"
126 "STACKSIZE = %hu\n"
127 "CS : IP = %04hXH:%04hXH"
128 ,ne.neSignature[0],ne.neSignature[1]
129 ,(int)ne.neLinkerVersion,(int)ne.neLinkerRevision
130 ,ne.neOffsetEntryTable
131 ,ne.neLengthEntryTable
132 ,ne.neChecksum
133 ,ne.neContestEXE
134 ,__nedata[ne.neContestEXE & 0x03]
135 ,GetBool( ne.neContestEXE & 0x0004 )
136 ,GetBool( ne.neContestEXE & 0x0008 )
137 ,GetBool( ne.neContestEXE & 0x0010 )
138 ,GetBool( ne.neContestEXE & 0x0020 )
139 ,GetBool( ne.neContestEXE & 0x0040 )
140 ,GetBool( ne.neContestEXE & 0x0040 )
141 ,GetPMWinAPI(ne.neContestEXE)
142 ,GetBool( ne.neContestEXE & 0x0800 )
143 ,GetBool( ne.neContestEXE & 0x2000 )
144 ,GetBool( ne.neContestEXE & 0x4000 )
145 ,GetBool( ne.neContestEXE & 0x8000 )
146 ,ne.neAutoDataSegmentCount
147 ,ne.neHeapSize
148 ,ne.neStackSize
149 ,(unsigned)(ne.neCSIPvalue >> 16),(unsigned)(ne.neCSIPvalue & 0xFFFF));
150 }
151
152 static __filesize_t entryNE;
153
PaintNewHeaderNE_2(void)154 static void __NEAR__ PaintNewHeaderNE_2( void )
155 {
156 twPrintF("SS : SP = %04hXH:%04hXH\n"
157 "Segment Table Count = %hu\n"
158 "Module Reference Table Count = %hu\n"
159 "Length Non Resident Name Table = %hu\n"
160 "Segment Table Offset = %hXH\n"
161 "Resource Table Offset = %hXH\n"
162 "Resident Name Table Offset = %hXH\n"
163 "Module Reference Table Offset = %hXH\n"
164 "Import Table Offset = %hXH\n"
165 "Non Resident Name Table Offset = %08lXH\n"
166 "Moveable Entry Point Count = %hu\n"
167 "Logical Sector Shift Count = %hu\n"
168 "Resource Segment Count = %hu\n"
169 "Operating System = %s\n"
170 "[%c] - Support for long file names\n"
171 "[%c] - Windows 2.x API runs in prot. mode\n"
172 "[%c] - Windows 2.x API getting prot. font\n"
173 "[%c] - WLO application on OS/2\n"
174 ,(unsigned short)(ne.neSSSPvalue >> 16),(unsigned short)(ne.neSSSPvalue & 0xFFFF)
175 ,(short)ne.neSegmentTableCount
176 ,ne.neModuleReferenceTableCount
177 ,ne.neLengthNonResidentNameTable
178 ,ne.neOffsetSegmentTable
179 ,ne.neOffsetResourceTable
180 ,ne.neOffsetResidentNameTable
181 ,ne.neOffsetModuleReferenceTable
182 ,ne.neOffsetImportTable
183 ,ne.neOffsetNonResidentNameTable
184 ,ne.neMoveableEntryPointCount
185 ,ne.neLogicalSectorShiftCount
186 ,ne.neResourceSegmentCount
187 ,__getNEType(ne.neOperatingSystem)
188 ,GetBool(ne.neFlagsOther & 0x01)
189 ,GetBool(ne.neFlagsOther & 0x02)
190 ,GetBool(ne.neFlagsOther & 0x02)
191 ,GetBool(ne.neFlagsOther & 0x80));
192 if(ne.neOperatingSystem == 2)
193 {
194 /* Correction by Olivier Mengu\u00e9*/
195 unsigned char high,low;
196 high = ne.neWindowsVersion >> 8;
197 low = ne.neWindowsVersion & 0xFF;
198 /* End of correction */
199 twSetColorAttr(dialog_cset.addinfo);
200 twPrintF("Offset of Fast Load Area = %04hXH"
201 ,ne.neOffsetFastLoadArea); twClrEOL();
202 twPrintF("\nLength of Fast Load Area = %hu"
203 ,ne.neLengthFastLoadArea); twClrEOL();
204 twPrintF("\nWindows version = %02hu.%02hu"
205 ,(unsigned int)high,(unsigned int)low); twClrEOL();
206 twPrintF("\n");
207 }
208 twSetColorAttr(dialog_cset.entry);
209 twPrintF(">Entry Point %s = %08XH",( ne.neContestEXE & 32768L ) ? "[ LibEntry ] " : "[ EXEEntry ] ",entryNE);
210 twClrEOL();
211 twSetColorAttr(dialog_cset.main);
212 }
213
214 static void (__NEAR__ * nephead[])( void ) =
215 {
216 PaintNewHeaderNE_1,
217 PaintNewHeaderNE_2
218 };
219
PaintNewHeaderNE(TWindow * win,const void ** ptr,unsigned npage,unsigned tpage)220 static void __FASTCALL__ PaintNewHeaderNE(TWindow * win,const void **ptr,unsigned npage,unsigned tpage)
221 {
222 char text[80];
223 UNUSED(ptr);
224 twUseWin(win);
225 twFreezeWin(win);
226 twClearWin();
227 sprintf(text," New Executable Header [%d/%d] ",npage + 1,tpage);
228 twSetTitleAttr(win,text,TW_TMODE_CENTER,dialog_cset.title);
229 twSetFooterAttr(win,PAGEBOX_SUB,TW_TMODE_RIGHT,dialog_cset.selfooter);
230 if(npage < 2)
231 {
232 twGotoXY(1,1);
233 (*(nephead[npage]))();
234 }
235 twRefreshFullWin(win);
236 }
237
ShowNewHeaderNE(void)238 static __filesize_t __FASTCALL__ ShowNewHeaderNE( void )
239 {
240 __fileoff_t pos;
241 unsigned CS,IP;
242 CS = (unsigned)((ne.neCSIPvalue) >> 16); /** segment number */
243 IP = (unsigned)(ne.neCSIPvalue & 0xFFFF); /** offset within segment */
244 entryNE = CalcEntryPointNE(CS,IP);
245 pos = BMGetCurrFilePos();
246 if(PageBox(70,22,NULL,2,PaintNewHeaderNE) != -1 && entryNE) pos = entryNE;
247 return pos;
248 }
249
entpaintNE(const ENTRY * nam,unsigned flags)250 static void __NEAR__ __FASTCALL__ entpaintNE(const ENTRY *nam,unsigned flags)
251 {
252 twGotoXY(1,1);
253 twPrintF("Entry Point for %s segment\n"
254 "Entry point is %s EXPORTED\n"
255 "The Entry %s uses SHARED data segment\n"
256 "Numbers of word that compose the stack %u\n"
257 "Segment offset = %XH bytes\n"
258 "Segment number = %u"
259 ,(unsigned char)(nam->eFixed) == 0xFF ? "MOVEABLE" : "FIXED"
260 ,flags & 0x0001 ? " " : "NO"
261 ,flags & 0x0002 ? " " : "NO"
262 ,(flags & 0xFFF4 >> 2)
263 ,nam->eSegOff
264 ,((unsigned)((unsigned char)(nam->eSegNum))));
265 }
266
paintdummyentryNE(void)267 static void __NEAR__ __FASTCALL__ paintdummyentryNE( void )
268 {
269 twGotoXY(1,3);
270 twPrintF(" Entry point not present ( Dummy bungle )");
271 }
272
SegPaintNE(TWindow * win,const void ** names,unsigned start,unsigned nlist)273 static void __FASTCALL__ SegPaintNE(TWindow * win,const void ** names,unsigned start,unsigned nlist)
274 {
275 char buffer[81];
276 const SEGDEF ** nam = (const SEGDEF **)names;
277 unsigned flags = nam[start]->sdFlags;
278 twUseWin(win);
279 twFreezeWin(win);
280 twClearWin();
281 sprintf(buffer," Segment Table [ %u / %u ] ",start + 1,nlist);
282 twSetTitleAttr(win,buffer,TW_TMODE_CENTER,dialog_cset.title);
283 twSetFooterAttr(win,PAGEBOX_SUB,TW_TMODE_RIGHT,dialog_cset.selfooter);
284 twGotoXY(1,1);
285 if(nam[start]->sdOffset)
286 twPrintF("Relative offset from begining in sectors = %04hXH\n"
287 ,nam[start]->sdOffset);
288 else
289 twPrintF("No data of segment in the file\n");
290 twPrintF("Length of segments = %hu bytes\n"
291 "Minimum allocated memory for segment = %hu bytes\n"
292 "Segment is : %s\n"
293 " [%c] - Loader has allocated memory for segment\n"
294 " [%c] - Iterated segment\n"
295 "Segment is : %s\n"
296 "Segment is : %s\n"
297 "Segment is : %s\n"
298 "Segment is : %s\n"
299 " [%c] - Segment contains relocation data\n"
300 "Segment is : %s\n"
301 "IOPL : %hu\n"
302 "Segment is : %s\n"
303 "Segment bitness : %d\n"
304 " [%c] - Huge memory segment (sizes is sector units)\n"
305 " [%c] - GDT allocation requested"
306 ,nam[start]->sdLength ? nam[start]->sdLength : (unsigned short)0xFFFF
307 ,nam[start]->sdMinMemory ? nam[start]->sdMinMemory : (unsigned short)0xFFFF
308 ,(flags & 0x0001) ? "DATA" : "CODE"
309 ,GetBool((flags & 0x0002) == 0x0002)
310 ,GetBool((flags & 0x0004) == 0x0004)
311 ,(flags & 0x0010) ? "MOVEABLE" : "FIXED"
312 ,(flags & 0x0020) ? "PURE" : "IMPURE"
313 ,(flags & 0x0040) ? "PRELOAD" : "LOADONCALL"
314 ,(flags & 0x0080) ? (flags & 0x0001) ? "READONLY" : "EXECUTEONLY" : (flags & 0x0001) ? "READWRITE" : "DEBUGABLE"
315 ,GetBool((flags & 0x0100) == 0x0100)
316 ,(flags & 0x0200) ? (flags & 0x0001) ? "EXPAND DOWN" : "CONFORMING" : (flags & 0x0001) ? "EXPAND UP" : "NOCONFORMING"
317 ,(unsigned)(((flags & 0x0C00) >> 10) & 0x03)
318 ,(flags & 0x1000) ? "DISCARDABLE" : "NONDISCARDABLE"
319 ,(flags & 0x2000) ? 32 : 16
320 ,GetBool((flags & 0x4000) == 0x0400)
321 ,GetBool((flags & 0x8000) == 0x0800));
322 twRefreshFullWin(win);
323 }
324
EntPaintNE(TWindow * win,const void ** names,unsigned start,unsigned nlist)325 static void __FASTCALL__ EntPaintNE(TWindow * win,const void ** names,unsigned start,unsigned nlist)
326 {
327 char buffer[81];
328 const ENTRY ** nam = (const ENTRY **)names;
329 unsigned flags = nam[start]->eFlags;
330 twUseWin(win);
331 twFreezeWin(win);
332 twClearWin();
333 sprintf(buffer," Entry Point [ %u / %u ] ",start + 1,nlist);
334 twSetTitleAttr(win,buffer,TW_TMODE_CENTER,dialog_cset.title);
335 twSetFooterAttr(win,PAGEBOX_SUB,TW_TMODE_RIGHT,dialog_cset.selfooter);
336 if(nam[start]->eFixed) entpaintNE(nam[start],flags);
337 else paintdummyentryNE();
338 twRefreshFullWin(win);
339 }
340
__ReadModRefNamesNE(BGLOBAL handle,memArray * obj)341 static tBool __FASTCALL__ __ReadModRefNamesNE(BGLOBAL handle,memArray * obj)
342 {
343 unsigned i;
344 tUIntFast16 offTable;
345 bioSeek(handle,ne.neOffsetModuleReferenceTable + headshift,SEEKF_START);
346 for(i = 0;i < ne.neModuleReferenceTableCount;i++)
347 {
348 __filesize_t NameOff;
349 unsigned char length;
350 __filesize_t fp;
351 char stmp[256];
352 offTable = bioReadWord(handle);
353 fp = bioTell(handle);
354 NameOff = (__fileoff_t)headshift + offTable + ne.neOffsetImportTable;
355 bioSeek(handle,NameOff,SEEKF_START);
356 length = bioReadByte(handle);
357 if(IsKbdTerminate() || bioEOF(handle)) break;
358 bioReadBuffer(handle,stmp,length);
359 stmp[length] = 0;
360 bioSeek(handle,fp,SEEKF_START);
361 if(!ma_AddString(obj,stmp,True)) break;
362 }
363 return True;
364 }
365
366 static void __FASTCALL__ ShowProcListNE(int);
367
ShowModRefNE(void)368 static __filesize_t __FASTCALL__ ShowModRefNE( void )
369 {
370 BGLOBAL handle;
371 int ret;
372 tBool bval;
373 unsigned nnames;
374 __filesize_t fret;
375 memArray * obj;
376 TWindow * w;
377 fret = BMGetCurrFilePos();
378 handle = ne_cache;
379 bioSeek(handle,0L,SEEK_SET);
380 if(!(nnames = ne.neModuleReferenceTableCount)) { NotifyBox(NOT_ENTRY,MOD_REFER); return fret; }
381 if(!(obj = ma_Build(nnames,True))) goto exit;
382 w = PleaseWaitWnd();
383 bval = __ReadModRefNamesNE(handle,obj);
384 CloseWnd(w);
385 if(bval)
386 {
387 while(1)
388 {
389 ret = ma_Display(obj,MOD_REFER,LB_SELECTIVE | LB_SORTABLE,-1);
390 if(ret != -1)
391 {
392 ShowProcListNE(ret);
393 }
394 else break;
395 }
396 }
397 ma_Destroy(obj);
398 exit:
399 return fret;
400 }
401
isPresent(memArray * arr,unsigned nentry,char * template)402 static tBool __NEAR__ __FASTCALL__ isPresent(memArray *arr,unsigned nentry,char *template)
403 {
404 unsigned i;
405 tBool ret = False;
406 if(nentry)
407 {
408 for(i = 0;i < nentry;i++)
409 {
410 if(strcmp((const char *)arr->data[i],template) == 0) { ret = True; break; }
411 }
412 }
413 return ret;
414 }
415
416
__ReadProcListNE(BGLOBAL handle,memArray * obj,int modno)417 static tBool __FASTCALL__ __ReadProcListNE(BGLOBAL handle,memArray * obj,int modno)
418 {
419 unsigned i,count;
420 char buff[256];
421 SEGDEF tsd;
422 modno++;
423 count = 0;
424
425 bioSeek(handle,headshift+ne.neOffsetSegmentTable,SEEKF_START);
426 for(i = 0;i < ne.neSegmentTableCount;i++)
427 {
428 bioReadBuffer(handle,&tsd,sizeof(SEGDEF));
429 if(tsd.sdLength && tsd.sdOffset && tsd.sdFlags & 0x0100)
430 {
431 __filesize_t spos;
432 tUIntFast16 j,nrelocs;
433 RELOC_NE rne;
434 spos = bioTell(handle);
435 bioSeek(handle,((__fileoff_t)(tsd.sdOffset) << ne.neLogicalSectorShiftCount) + tsd.sdLength,SEEKF_START);
436 nrelocs = bioReadWord(handle);
437 for(j = 0;j < nrelocs;j++)
438 {
439 bioReadBuffer(handle,&rne,sizeof(RELOC_NE));
440 if((rne.Type & 3) && rne.idx == modno)
441 {
442 if((rne.Type & 3) == 1)
443 {
444 sprintf(buff,"< By ordinal > @%hu",rne.ordinal);
445 }
446 else
447 {
448 rd_ImpName(buff,sizeof(buff),rne.ordinal,True);
449 }
450 if(!isPresent(obj,count,buff))
451 {
452 if(IsKbdTerminate()) goto exit;
453 if(!ma_AddString(obj,buff,True)) goto exit;
454 }
455 }
456 }
457 bioSeek(handle,spos,SEEKF_START);
458 }
459 }
460 exit:
461 return True;
462 }
463
ShowProcListNE(int modno)464 static void __FASTCALL__ ShowProcListNE( int modno )
465 {
466 BGLOBAL handle;
467 char ptitle[80],name[50];
468 tBool __bool;
469 memArray* obj;
470 TWindow *w;
471 handle = ne_cache;
472 bioSeek(handle,0L,SEEK_SET);
473 w = PleaseWaitWnd();
474 if(!(obj = ma_Build(0,True))) return;
475 __bool = __ReadProcListNE(handle,obj,modno);
476 CloseWnd(w);
477 if(__bool)
478 {
479 if(!obj->nItems) { NotifyBox(NOT_ENTRY,MOD_REFER); return; }
480 rd_ImpName(name,sizeof(name),modno+1,False);
481 sprintf(ptitle,"%s%s ",IMPPROC_TABLE,name);
482 ma_Display(obj,ptitle,LB_SORTABLE,-1);
483 }
484 ma_Destroy(obj);
485 }
486 #if 0
487 static int RNRprevind = -3;
488 static long RNRprevshift = 0;
489
490 static unsigned __FASTCALL__ RNameReadFull(BGLOBAL handle,char * names,unsigned nindex,unsigned long offset)
491 {
492 unsigned char length;
493 tUIntFast16 Ordinal;
494 unsigned i;
495 if(RNRprevind == (nindex - 1) && RNRprevshift) bioSeek(handle,RNRprevshift,SEEKF_START);
496 else
497 {
498 bioSeek(handle,offset,SEEKF_START);
499 for(i = 0;i < nindex;i++)
500 {
501 length = bioReadByte(handle);
502 bioSeek(handle,length + 2,SEEKF_CUR);
503 }
504 }
505 length = bioReadByte(handle);
506 bioReadBuffer(handle,(void *)names,length);
507 names[length] = 0;
508 Ordinal = bioReadWord(handle);
509 RNRprevind = nindex;
510 RNRprevshift = bioTell(handle);
511 return Ordinal;
512 }
513
514 static unsigned __FASTCALL__ ResNameReadFull(BGLOBAL handle,char * names,unsigned nindex)
515 {
516 return RNameReadFull(handle,names,nindex,ne.neOffsetResidentNameTable + headshift);
517 }
518
519 static unsigned __FASTCALL__ NResNameReadFull(BGLOBAL handle,char * names,unsigned nindex)
520 {
521 return RNameReadFull(handle,names,nindex,ne.neOffsetNonResidentNameTable);
522 }
523 #endif
RNamesReadItems(BGLOBAL handle,memArray * obj,unsigned nnames,__filesize_t offset)524 tBool __FASTCALL__ RNamesReadItems(BGLOBAL handle,memArray * obj,unsigned nnames,__filesize_t offset)
525 {
526 unsigned char length;
527 unsigned Ordinal;
528 unsigned i;
529 char stmp[300]; /* max255 + @ordinal */
530 bioSeek(handle,offset,SEEKF_START);
531 for(i = 0;i < nnames;i++)
532 {
533 length = bioReadByte(handle);
534 if(IsKbdTerminate() || bioEOF(handle)) break;
535 bioReadBuffer(handle,stmp,length);
536 Ordinal = bioReadWord(handle);
537 sprintf(&stmp[length],"%c%-5u",LB_ORD_DELIMITER, Ordinal);
538 if(!ma_AddString(obj,stmp,True)) break;
539 }
540 return True;
541 }
542
NERNamesReadItems(BGLOBAL handle,memArray * names,unsigned nnames)543 static tBool __FASTCALL__ NERNamesReadItems(BGLOBAL handle,memArray * names,unsigned nnames)
544 {
545 return RNamesReadItems(handle,names,nnames,ne.neOffsetResidentNameTable + headshift);
546 }
547
NENRNamesReadItems(BGLOBAL handle,memArray * names,unsigned nnames)548 static tBool __FASTCALL__ NENRNamesReadItems(BGLOBAL handle,memArray * names,unsigned nnames)
549 {
550 return RNamesReadItems(handle,names,nnames,ne.neOffsetNonResidentNameTable);
551 }
552
__ReadSegTableNE(BGLOBAL handle,memArray * obj,unsigned nnames)553 static tBool __NEAR__ __FASTCALL__ __ReadSegTableNE(BGLOBAL handle,memArray * obj,unsigned nnames)
554 {
555 unsigned i;
556 for(i = 0;i < nnames;i++)
557 {
558 SEGDEF sd;
559 if(IsKbdTerminate() || bioEOF(handle)) break;
560 bioReadBuffer(handle,&sd,sizeof(SEGDEF));
561 if(!ma_AddData(obj,&sd,sizeof(SEGDEF),True)) break;
562 }
563 return True;
564 }
565
GetNamCountNE(BGLOBAL handle,__filesize_t offset)566 unsigned __FASTCALL__ GetNamCountNE(BGLOBAL handle,__filesize_t offset )
567 {
568 unsigned i;
569 i = 0;
570 if(!offset) return 0;
571 bioSeek(handle,offset,SEEKF_START);
572 while(1)
573 {
574 unsigned char l;
575 l = bioReadByte(handle);
576 if(l == 0 || bioEOF(handle)) break;
577 bioSeek(handle,l + 2,SEEKF_CUR);
578 i++;
579 if(i > 0xFFFD) break;
580 }
581 return i;
582 }
583
NERNamesNumItems(BGLOBAL handle)584 static unsigned __FASTCALL__ NERNamesNumItems(BGLOBAL handle)
585 {
586 return GetNamCountNE(handle,headshift + ne.neOffsetResidentNameTable);
587 }
588
NENRNamesNumItems(BGLOBAL handle)589 static unsigned __FASTCALL__ NENRNamesNumItems(BGLOBAL handle)
590 {
591 return GetNamCountNE(handle,ne.neOffsetNonResidentNameTable);
592 }
593
ReadEntryItemNE(BGLOBAL handle,ENTRY * obj,unsigned char etype)594 static void __FASTCALL__ ReadEntryItemNE(BGLOBAL handle,ENTRY * obj,unsigned char etype)
595 {
596 obj->eFixed = etype;
597 if(etype)
598 {
599 if(etype == 0xFF)
600 {
601 obj->eFlags = bioReadByte(handle);
602 bioSeek(handle,2,SEEKF_CUR); /** int 3F */
603 obj->eSegNum = bioReadByte(handle);
604 obj->eSegOff = bioReadWord(handle);
605 }
606 else
607 {
608 obj->eFlags = bioReadByte(handle);
609 obj->eSegOff = bioReadWord(handle);
610 }
611 }
612 if(etype != 0xFE && etype != 0xFF) obj->eSegNum = etype;
613 }
614
SkipEntryItemNE(BGLOBAL handle,unsigned char etype)615 static void __NEAR__ __FASTCALL__ SkipEntryItemNE(BGLOBAL handle,unsigned char etype)
616 {
617 if(etype)
618 {
619 if(etype == 0xFF) bioSeek(handle,6,SEEKF_CUR); /** moveable */
620 else
621 bioSeek(handle,3,SEEKF_CUR); /** fixed */
622 }
623 }
624
ReadEntryNE(ENTRY * obj,unsigned entnum)625 static tBool __FASTCALL__ ReadEntryNE(ENTRY * obj,unsigned entnum)
626 {
627 BGLOBAL handle;
628 unsigned i,j;
629 unsigned char nentry,etype;
630 handle = ne_cache1;
631 bioSeek(handle,(__fileoff_t)headshift + ne.neOffsetEntryTable,SEEK_SET);
632 i = 0;
633 while(1)
634 {
635 nentry = bioReadByte(handle);
636 if(nentry == 0 || bioEOF(handle)) break;
637 etype = bioReadByte(handle);
638 for(j = 0;j < nentry;j++,i++)
639 {
640 if(i == entnum - 1)
641 {
642 ReadEntryItemNE(handle,(ENTRY *)obj,etype);
643 return True;
644 }
645 else SkipEntryItemNE(handle,etype);
646 }
647 }
648 return False;
649 }
650
ReadSegDefNE(SEGDEF * obj,unsigned segnum)651 static tBool __FASTCALL__ ReadSegDefNE(SEGDEF * obj,unsigned segnum)
652 {
653 BGLOBAL handle;
654 handle = ne_cache3;
655 if(segnum > ne.neSegmentTableCount || !segnum) return False;
656 bioSeek(handle,(__fileoff_t)headshift + ne.neOffsetSegmentTable + (segnum - 1)*sizeof(SEGDEF),BM_SEEK_SET);
657 bioReadBuffer(handle,(void *)obj,sizeof(SEGDEF));
658 return True;
659 }
660
CalcEntryPointNE(unsigned segnum,unsigned offset)661 static __filesize_t __NEAR__ __FASTCALL__ CalcEntryPointNE( unsigned segnum, unsigned offset )
662 {
663 SEGDEF seg;
664 __filesize_t shift;
665 if(!ReadSegDefNE(&seg,segnum)) return 0;
666 shift = seg.sdOffset ? (((unsigned long)seg.sdOffset)<<ne.neLogicalSectorShiftCount) + offset : 0L;
667 return shift;
668 }
669
CalcEntryNE(unsigned ord,tBool dispmsg)670 static __filesize_t __NEAR__ __FASTCALL__ CalcEntryNE(unsigned ord,tBool dispmsg)
671 {
672 ENTRY entr;
673 SEGDEF segd;
674 int segnum;
675 if(!ReadEntryNE(&entr,ord)) { if(dispmsg) ErrMessageBox(NOT_ENTRY,NULL); return 0L; }
676 if(entr.eFixed == 0xFE)
677 {
678 char outs[100];
679 if(dispmsg)
680 {
681 sprintf(outs,"This entry is constant : %04hXH",entr.eSegOff);
682 TMessageBox(outs,"Virtual entry");
683 }
684 return 0L;
685 }
686 else segnum = entr.eSegNum;
687 if(ReadSegDefNE(&segd,segnum))
688 {
689 return segd.sdOffset ? (((__filesize_t)segd.sdOffset)<<ne.neLogicalSectorShiftCount) + entr.eSegOff : 0L;
690 }
691 else if(dispmsg) ErrMessageBox(NO_ENTRY,BAD_ENTRY);
692 return 0L;
693 }
694
ShowSegDefNE(void)695 static __filesize_t __FASTCALL__ ShowSegDefNE( void )
696 {
697 BGLOBAL handle;
698 unsigned nnames;
699 __filesize_t fpos;
700 memArray * obj;
701 nnames = ne.neSegmentTableCount;
702 fpos = BMGetCurrFilePos();
703 if(!nnames) { NotifyBox(NOT_ENTRY," Segment Definition "); return fpos; }
704 if(!(obj = ma_Build(nnames,True))) return fpos;
705 handle = ne_cache;
706 bioSeek(handle,(__fileoff_t)headshift + ne.neOffsetSegmentTable,SEEK_SET);
707 if(__ReadSegTableNE(handle,obj,nnames))
708 {
709 int i;
710 i = PageBox(65,17,(const void **)obj->data,obj->nItems,SegPaintNE) + 1;
711 if(i > 0)
712 {
713 fpos = ((__filesize_t)((const SEGDEF *)obj->data[i-1])->sdOffset)<<ne.neLogicalSectorShiftCount;
714 }
715 }
716 ma_Destroy(obj);
717 return fpos;
718 }
719
__ReadEntryTableNE(BGLOBAL handle,memArray * obj)720 static tBool __NEAR__ __FASTCALL__ __ReadEntryTableNE(BGLOBAL handle,memArray * obj)
721 {
722 unsigned i;
723 unsigned char j,nentry;
724 i = 0;
725 while(1)
726 {
727 unsigned char etype;
728 nentry = bioReadByte(handle);
729 if(nentry == 0 || bioEOF(handle)) break;
730 etype = bioReadByte(handle);
731 for(j = 0;j < nentry;j++,i++)
732 {
733 ENTRY ent;
734 if(IsKbdTerminate()) break;
735 ReadEntryItemNE(handle,&ent,etype);
736 if(!ma_AddData(obj,&ent,sizeof(ENTRY),True)) break;
737 }
738 }
739 return True;
740 }
741
GetEntryCountNE(void)742 static unsigned __FASTCALL__ GetEntryCountNE( void )
743 {
744 BGLOBAL handle;
745 unsigned i,j;
746 unsigned char nentry;
747 handle = ne_cache;
748 bioSeek(handle,(__fileoff_t)headshift + ne.neOffsetEntryTable,SEEK_SET);
749 i = 0;
750 while(1)
751 {
752 unsigned char etype;
753 nentry = bioReadByte(handle);
754 if(nentry == 0 || bioEOF(handle)) break; /** end of table */
755 else
756 {
757 etype = bioReadByte(handle);
758 for(j = 0;j < nentry;j++,i++) { SkipEntryItemNE(handle,etype); if(i > 0xFFFD || IsKbdTerminate()) goto exit; }
759 }
760 }
761 exit:
762 return i;
763 }
764
ShowEntriesNE(void)765 static __filesize_t __FASTCALL__ ShowEntriesNE( void )
766 {
767 BGLOBAL handle;
768 unsigned nnames;
769 __filesize_t fpos;
770 memArray * obj;
771 nnames = GetEntryCountNE();
772 fpos = BMGetCurrFilePos();
773 if(!nnames) { NotifyBox(NOT_ENTRY," Entries "); return fpos; }
774 if(!(obj = ma_Build(nnames,True))) return fpos;
775 handle = ne_cache;
776 bioSeek(handle,(__fileoff_t)headshift + ne.neOffsetEntryTable,SEEK_SET);
777 if(__ReadEntryTableNE(handle,obj))
778 {
779 int i;
780 i = PageBox(50,6,(const void **)obj->data,obj->nItems,EntPaintNE) + 1;
781 if(i > 0) fpos = CalcEntryNE(i,True);
782 }
783 ma_Destroy(obj);
784 return fpos;
785 }
786
787 const char * ResourceGrNames[] =
788 {
789 "RESERVED 0",
790 "CURSOR",
791 "BITMAP",
792 "ICON",
793 "MENU",
794 "DIALOG",
795 "STRINGTABLE",
796 "FONTDIR",
797 "FONT",
798 "ACCELERATOR",
799 "RCDATA",
800 "RESERVED 11",
801 "GROUP CURSOR",
802 "RESERVED 13",
803 "GROUP ICON",
804 "NAME TABLE",
805 "VERSIONINFO"
806 };
807
GetResourceIDNE(BGLOBAL handle,unsigned rid,__filesize_t BegResTab)808 static char * __NEAR__ __FASTCALL__ GetResourceIDNE(BGLOBAL handle,unsigned rid,__filesize_t BegResTab)
809 {
810 static char buff[30];
811 unsigned char nByte;
812 if(rid & 0x8000) sprintf(buff,"%hi",rid & 0x7FFF);
813 else
814 {
815 __filesize_t pos;
816 pos = bioTell(handle);
817 bioSeek(handle,BegResTab + rid,SEEKF_START);
818 nByte = bioReadByte(handle);
819 if(nByte > 26)
820 {
821 bioReadBuffer(handle,buff,26);
822 strcat(buff,"...");
823 nByte = 29;
824 }
825 else if(nByte) bioReadBuffer(handle,buff,nByte);
826 buff[nByte] = 0;
827 bioSeek(handle,pos,SEEKF_START);
828 }
829 return buff;
830 }
831
__ReadResourceGroupNE(BGLOBAL handle,memArray * obj,unsigned nitems,long * addr)832 static tBool __NEAR__ __FASTCALL__ __ReadResourceGroupNE(BGLOBAL handle,memArray *obj,unsigned nitems,long * addr)
833 {
834 unsigned i,j;
835 tUIntFast16 rcAlign,rTypeID,rcount;
836 unsigned long BegResTab;
837 char buff[81];
838 BegResTab = bioTell(handle);
839 rcAlign = bioReadWord(handle);
840 for(i = 0;i < nitems;i++)
841 {
842 addr[i++] = bioTell(handle);
843 rTypeID = bioReadWord(handle);
844 rcount = bioReadWord(handle);
845 bioSeek(handle,4,SEEKF_CUR);
846 if(IsKbdTerminate() || bioEOF(handle)) break;
847 if(rTypeID & 0x8000)
848 {
849 rTypeID &= 0x7FFF;
850 if(rTypeID < 17) strcpy(buff,ResourceGrNames[rTypeID]);
851 else sprintf(buff,"< Ordinal type: %04hXH >",rTypeID);
852 }
853 else sprintf(buff,"\"%s\"",GetResourceIDNE(handle,rTypeID,BegResTab));
854 if(!ma_AddString(obj,buff,True)) break;
855 for(j = 0;j < rcount;j++)
856 {
857 NAMEINFO nam;
858 char stmp[81];
859 if(IsKbdTerminate() || bioEOF(handle)) break;
860 bioReadBuffer(handle,&nam,sizeof(NAMEINFO));
861 addr[i++] = ((unsigned long)nam.rnOffset)<<rcAlign;
862 sprintf(stmp," %s <length: %04hXH> %s %s %s",
863 GetResourceIDNE(handle,nam.rnID,BegResTab),
864 (unsigned)((unsigned long)nam.rnLength)<<rcAlign,
865 ((nam.rnFlags & 0x0010) ? "MOVEABLE" : "FIXED"),
866 ((nam.rnFlags & 0x0020) ? "PURE" : "IMPURE"),
867 ((nam.rnFlags & 0x0040) ? "PRELOAD" : "LOADONCALL")
868 );
869 if(!ma_AddString(obj,stmp,True)) goto exit;
870 }
871 i--;
872 }
873 exit:
874 return True;
875 }
876
GetResourceGroupCountNE(BGLOBAL handle)877 static unsigned int __NEAR__ __FASTCALL__ GetResourceGroupCountNE(BGLOBAL handle)
878 {
879 tUIntFast16 rcount, rTypeID;
880 int count = 0;
881 __filesize_t pos;
882 if(ne.neOffsetResourceTable == ne.neOffsetResidentNameTable) return 0;
883 pos = bioTell(handle);
884 bioSeek(handle,2L,SEEKF_CUR); /** rcAlign */
885 while(1)
886 {
887 rTypeID = bioReadWord(handle);
888 if(rTypeID)
889 {
890 rcount = bioReadWord(handle);
891 bioSeek(handle,rcount*sizeof(NAMEINFO) + 4,SEEKF_CUR);
892 count += rcount + 1;
893 if(count > 0xF000 || IsKbdTerminate() || bioEOF(handle)) break;
894 }
895 else break;
896 }
897 bioSeek(handle,pos,SEEKF_START);
898 return count;
899 }
900
ShowResourcesNE(void)901 static __filesize_t __FASTCALL__ ShowResourcesNE( void )
902 {
903 __filesize_t fpos;
904 BGLOBAL handle;
905 memArray* rgroup;
906 long * raddr;
907 unsigned nrgroup;
908 fpos = BMGetCurrFilePos();
909 handle = ne_cache;
910 bioSeek(handle,(__fileoff_t)headshift + ne.neOffsetResourceTable,SEEK_SET);
911 if(!(nrgroup = GetResourceGroupCountNE(handle))) { NotifyBox(NOT_ENTRY," Resources "); return fpos; }
912 if(!(rgroup = ma_Build(nrgroup,True))) goto exit;
913 if(!(raddr = PMalloc(nrgroup*sizeof(long)))) return fpos;
914 if(__ReadResourceGroupNE(handle,rgroup,nrgroup,raddr))
915 {
916 int i;
917 i = ma_Display(rgroup," Resource groups : ",LB_SELECTIVE,-1);
918 if(i != -1) fpos = raddr[i];
919 }
920 free(raddr);
921 ma_Destroy(rgroup);
922 exit:
923 return fpos;
924 }
925
ShowResNamNE(void)926 static __filesize_t __FASTCALL__ ShowResNamNE( void )
927 {
928 __filesize_t fpos = BMGetCurrFilePos();
929 int ret;
930 unsigned ordinal;
931 ret = fmtShowList(NERNamesNumItems,NERNamesReadItems,
932 RES_NAMES,
933 LB_SELECTIVE | LB_SORTABLE,&ordinal);
934 if(ret != -1)
935 {
936 fpos = CalcEntryNE(ordinal,True);
937 }
938 return fpos;
939 }
940
ShowNResNmNE(void)941 static __filesize_t __FASTCALL__ ShowNResNmNE( void )
942 {
943 __filesize_t fpos;
944 fpos = BMGetCurrFilePos();
945 {
946 int ret;
947 unsigned ordinal;
948 ret = fmtShowList(NENRNamesNumItems,NENRNamesReadItems,
949 NORES_NAMES,
950 LB_SELECTIVE | LB_SORTABLE,&ordinal);
951 if(ret != -1)
952 {
953 fpos = CalcEntryNE(ordinal,True);
954 }
955 }
956 return fpos;
957 }
958
IsNEFormat(void)959 static tBool __FASTCALL__ IsNEFormat( void )
960 {
961 char id[2];
962 headshift = IsNewExe();
963 if(headshift)
964 {
965 bmReadBufferEx(id,sizeof(id),headshift,SEEKF_START);
966 if(id[0] == 'N' && id[1] == 'E') return True;
967 }
968 return False;
969 }
970
971 /***************************************************************************/
972 /************************ RELOCATION FOR NE *******************************/
973 /***************************************************************************/
974
975 typedef struct tagNERefChain
976 {
977 unsigned offset;
978 unsigned number;
979 }NERefChain;
980
981 static unsigned CurrChainSegment = 0xFFFF;
982 static unsigned long CurrSegmentStart = 0;
983 static unsigned long CurrSegmentLength = 0;
984 static int CurrSegmentHasReloc = -1;
985 static linearArray *CurrNEChain = NULL;
986 static char __codelen,__type;
987
compare_chains(const void __HUGE__ * v1,const void __HUGE__ * v2)988 static tCompare __FASTCALL__ compare_chains(const void __HUGE__ *v1,const void __HUGE__ *v2)
989 {
990 const NERefChain __HUGE__ * c1,__HUGE__ * c2;
991 c1 = (const NERefChain __HUGE__ *)v1;
992 c2 = (const NERefChain __HUGE__ *)v2;
993 return __CmpLong__(c1->offset,c2->offset);
994 }
995
996
BuildNERefChain(__filesize_t segoff,__filesize_t slength)997 static void __NEAR__ __FASTCALL__ BuildNERefChain(__filesize_t segoff,__filesize_t slength)
998 {
999 unsigned nchains,i;
1000 __filesize_t reloc_off;
1001 TWindow * w,*usd;
1002 usd = twUsedWin();
1003 if(!(CurrNEChain = la_Build(0,sizeof(NERefChain),MemOutBox))) return;
1004 w = CrtDlgWndnls(SYSTEM_BUSY,49,1);
1005 twUseWin(w);
1006 twGotoXY(1,1);
1007 twPrintF(" Building reference chains for segment #%u",CurrChainSegment);
1008 twUseWin(usd);
1009 if(!PubNames) ne_ReadPubNameList(bmbioHandle(),MemOutBox);
1010 reloc_off = segoff + slength;
1011 nchains = bmReadWordEx(reloc_off,SEEKF_START);
1012 reloc_off += 2;
1013 for(i = 0;i < nchains;i++)
1014 {
1015 __filesize_t this_reloc_off;
1016 RELOC_NE rne;
1017 NERefChain nrc;
1018 this_reloc_off = reloc_off + i*sizeof(RELOC_NE);
1019 bmReadBufferEx(&rne,sizeof(RELOC_NE),this_reloc_off,SEEKF_START);
1020 if(IsKbdTerminate() || bmEOF()) break;
1021 nrc.offset = rne.RefOff;
1022 nrc.number = i;
1023 if(!la_AddData(CurrNEChain,&nrc,MemOutBox)) { OutOfMem: break; }
1024 if(!(rne.Type & 0x04) && rne.AddrType) /** if not additive fixup and not byte fixup */
1025 {
1026 while(1)
1027 {
1028 unsigned next_off;
1029 next_off = bmReadWordEx(segoff + (__filesize_t)((NERefChain __HUGE__ *)CurrNEChain->data)[CurrNEChain->nItems - 1].offset,SEEKF_START);
1030 if(bmEOF()) break;
1031 if(next_off > slength || next_off == 0xFFFF || next_off == ((NERefChain __HUGE__ *)CurrNEChain->data)[CurrNEChain->nItems - 1].offset) break;
1032 nrc.offset = next_off;
1033 nrc.number = i;
1034 if(!la_AddData(CurrNEChain,&nrc,MemOutBox)) goto OutOfMem;
1035 }
1036 }
1037 }
1038 la_Sort(CurrNEChain,compare_chains);
1039 CloseWnd(w);
1040 }
1041
compare_ne_spec(const void __HUGE__ * e1,const void __HUGE__ * e2)1042 static tCompare __FASTCALL__ compare_ne_spec(const void __HUGE__ *e1,const void __HUGE__ *e2)
1043 {
1044 const NERefChain __HUGE__ *r1,__HUGE__ *r2;
1045 RELOC_NE rne;
1046 tCompare ret;
1047 r1 = e1;
1048 r2 = e2;
1049 if(r2->offset >= r1->offset && r2->offset < r1->offset + __codelen)
1050 {
1051 bmReadBufferEx(&rne,sizeof(RELOC_NE),CurrSegmentStart + CurrSegmentLength + 2 + sizeof(RELOC_NE)*r2->number,SEEKF_START);
1052 if(rne.Type == __type) return 0;
1053 }
1054 if(r1->offset < r2->offset) ret = -1;
1055 else ret = 1;
1056 return ret;
1057 }
1058
compare_ne(const void __HUGE__ * e1,const void __HUGE__ * e2)1059 static tCompare __FASTCALL__ compare_ne(const void __HUGE__ *e1,const void __HUGE__ *e2)
1060 {
1061 const NERefChain __HUGE__ *r1,__HUGE__ *r2;
1062 int ret;
1063 r1 = e1;
1064 r2 = e2;
1065 if(r2->offset >= r1->offset && r2->offset < r1->offset + __codelen) ret = 0;
1066 else
1067 if(r1->offset < r2->offset) ret = -1;
1068 else ret = 1;
1069 return ret;
1070 }
1071
__found_RNE(__filesize_t segoff,__filesize_t slength,unsigned segnum,unsigned keyoff,char codelen)1072 static RELOC_NE * __NEAR__ __FASTCALL__ __found_RNE(__filesize_t segoff,__filesize_t slength,unsigned segnum,unsigned keyoff,char codelen)
1073 {
1074 NERefChain *found,key;
1075 static RELOC_NE rne;
1076 if(segnum != CurrChainSegment || !CurrNEChain)
1077 {
1078 if(CurrNEChain) la_Destroy(CurrNEChain);
1079 CurrChainSegment = segnum;
1080 BuildNERefChain(segoff,slength);
1081 }
1082 key.offset = keyoff;
1083 __codelen = codelen;
1084 found = la_Find(CurrNEChain,&key,compare_ne);
1085 if(found) { bmReadBufferEx(&rne,sizeof(rne),segoff + slength + 2 + sizeof(RELOC_NE)*found->number,SEEKF_START); return &rne; }
1086 else return 0;
1087 }
1088
__found_RNE_spec(__filesize_t segoff,__filesize_t slength,unsigned segnum,unsigned keyoff,char codelen,int type)1089 static RELOC_NE * __NEAR__ __FASTCALL__ __found_RNE_spec(__filesize_t segoff,__filesize_t slength,unsigned segnum,unsigned keyoff,char codelen,int type)
1090 {
1091 NERefChain *found,key;
1092 static RELOC_NE rne;
1093 if(segnum != CurrChainSegment || !CurrNEChain)
1094 {
1095 if(CurrNEChain) la_Destroy(CurrNEChain);
1096 CurrChainSegment = segnum;
1097 BuildNERefChain(segoff,slength);
1098 }
1099 key.offset = keyoff;
1100 __codelen = codelen;
1101 __type = type;
1102 found = la_Find(CurrNEChain,&key,compare_ne_spec);
1103 if(found)
1104 {
1105 BGLOBAL b_cache;
1106 b_cache = ne_cache;
1107 bioSeek(b_cache,segoff + slength + 2 + sizeof(RELOC_NE)*found->number,SEEKF_START);
1108 bioReadBuffer(b_cache,&rne,sizeof(rne));
1109 return &rne;
1110 }
1111 else return 0;
1112 }
1113
__findSpecType(__filesize_t sstart,__filesize_t ssize,unsigned segnum,__filesize_t target,char codelen,char type,unsigned defval)1114 static unsigned __NEAR__ __FASTCALL__ __findSpecType(__filesize_t sstart,__filesize_t ssize,unsigned segnum,__filesize_t target,char codelen,char type,unsigned defval)
1115 {
1116 unsigned ret;
1117 RELOC_NE * rne;
1118 rne = __found_RNE_spec(sstart,ssize,segnum,(unsigned)(target - sstart),codelen,type);
1119 if(rne) ret = rne->ordinal;
1120 else ret = defval;
1121 return ret;
1122 }
1123
rdImpNameNELX(char * buff,int blen,unsigned idx,tBool useasoff,__filesize_t OffTable)1124 static void __NEAR__ __FASTCALL__ rdImpNameNELX(char *buff,int blen,unsigned idx,tBool useasoff,__filesize_t OffTable)
1125 {
1126 unsigned char len;
1127 __filesize_t name_off;
1128 BGLOBAL b_cache;
1129 b_cache = ne_cache2;
1130 name_off = OffTable;
1131 if(!useasoff)
1132 {
1133 __filesize_t ref_off;
1134 ref_off = (__filesize_t)headshift
1135 + ne.neOffsetModuleReferenceTable
1136 + (idx - 1)*2;
1137 name_off += bmReadWordEx(ref_off,SEEKF_START);
1138 }
1139 else name_off += idx;
1140 bioSeek(b_cache,name_off,SEEKF_START);
1141 len = bioReadByte(b_cache);
1142 len = len > blen ? blen : len;
1143 bioReadBuffer(b_cache,buff,len);
1144 buff[len] = 0;
1145 }
1146
rd_ImpName(char * buff,int blen,unsigned idx,tBool useasoff)1147 static void __FASTCALL__ rd_ImpName(char *buff,int blen,unsigned idx,tBool useasoff)
1148 {
1149 rdImpNameNELX(buff,blen,idx,useasoff,headshift + ne.neOffsetImportTable);
1150 }
1151
BuildReferStrNE(char * str,RELOC_NE * rne,int flags,__filesize_t ulShift)1152 static __filesize_t __NEAR__ __FASTCALL__ BuildReferStrNE(char *str,RELOC_NE *rne,int flags,__filesize_t ulShift)
1153 {
1154 char buff[256];
1155 const char *pref;
1156 __filesize_t retrf;
1157 char reflen;
1158 tBool need_virt;
1159 reflen = 0;
1160 pref = "";
1161 retrf = RAPREF_NONE;
1162 need_virt = (flags & APREF_SAVE_VIRT);
1163 switch(rne->AddrType)
1164 {
1165 case 0: reflen = 1; pref = "(b) "; break;
1166 case 2: reflen = 2; pref = "seg "; break;
1167 case 3: reflen = 4; pref = "seg:off16 "; break;
1168 case 5: reflen = 2; pref = "off16 "; break;
1169 case 11: reflen = 6; pref = "seg:off32 "; break;
1170 case 13: reflen = 4; pref = "off32 "; break;
1171 default: break;
1172 }
1173 if(flags & APREF_USE_TYPE) strcat(str,pref);
1174 if((rne->Type & 3) == 1 || (rne->Type & 3) == 2) /** imported type */
1175 {
1176 retrf = RAPREF_DONE;
1177 rd_ImpName(buff,sizeof(buff),rne->idx,0);
1178 sprintf(&str[strlen(str)],"<%s>.",buff);
1179 if((rne->Type & 3) == 1) sprintf(&str[strlen(str)],"@%hu",rne->ordinal);
1180 else
1181 {
1182 rd_ImpName(buff,sizeof(buff),rne->ordinal,True);
1183 strcat(str,buff);
1184 }
1185 }
1186 else
1187 if((rne->Type & 3) == 0)
1188 {
1189 if(rne->idx == 0x00FF && rne->AddrType != 2)
1190 {
1191 __filesize_t ea;
1192 ea = CalcEntryNE(rne->ordinal,False);
1193 if(FindPubName(buff,sizeof(buff),ea))
1194 sprintf(&str[strlen(str)],"%s",buff);
1195 else
1196 {
1197 retrf = ea;
1198 sprintf(&str[strlen(str)],"(*this).@%hu",rne->ordinal);
1199 }
1200 if(!DumpMode && !EditMode && !(flags & APREF_USE_TYPE)) GidAddGoAddress(str,ea);
1201 }
1202 else
1203 {
1204 __filesize_t ep;
1205 ep = CalcEntryPointNE(rne->idx,rne->ordinal);
1206 if(FindPubName(buff,sizeof(buff),ep))
1207 sprintf(&str[strlen(str)],"%s",buff);
1208 else
1209 {
1210 if(need_virt) sprintf(&str[strlen(str)],".%08lX",(unsigned long)nePA2VA(ep));
1211 else sprintf(&str[strlen(str)],"(*this).seg<#%hu>:%sH",rne->idx,Get4Digit(rne->ordinal));
1212 retrf = ep;
1213 }
1214 if(!DumpMode && !EditMode && !(flags & APREF_USE_TYPE)) GidAddGoAddress(str,ep);
1215 }
1216 }
1217 else
1218 {
1219 strcat(str,"?OSFIXUP?");
1220 }
1221 if((rne->Type & 4) == 4)
1222 {
1223 __filesize_t data;
1224 if(reflen && reflen <= 4)
1225 {
1226 strcat(str,"+");
1227 data = bmReadDWordEx(ulShift,SEEKF_START);
1228 strcat(str,reflen == 1 ? Get2Digit(data) : reflen == 2 ? Get4Digit(data) : Get8Digit(data));
1229 }
1230 else strcat(str,",<add>");
1231 }
1232 return retrf;
1233 }
1234
AppendNERef(char * str,__filesize_t ulShift,int flags,int codelen,__filesize_t r_sh)1235 static unsigned long __FASTCALL__ AppendNERef(char *str,__filesize_t ulShift,int flags,int codelen,__filesize_t r_sh)
1236 {
1237 unsigned i;
1238 __filesize_t segpos,slength;
1239 char buff[256];
1240 if(flags & APREF_TRY_PIC) return RAPREF_NONE;
1241 if(ulShift >= CurrSegmentStart && ulShift <= CurrSegmentStart + CurrSegmentLength)
1242 {
1243 i = CurrChainSegment - 1;
1244 if(CurrSegmentHasReloc) goto Direct;
1245 else goto TryLabel;
1246 }
1247 for(i = 0;i < ne.neSegmentTableCount;i++)
1248 {
1249 SEGDEF sd;
1250 ReadSegDefNE(&sd,i + 1);
1251 segpos = ((__filesize_t)sd.sdOffset) << ne.neLogicalSectorShiftCount;
1252 if(!segpos) continue;
1253 slength = sd.sdLength;
1254 if((sd.sdFlags & 0x4000) == 0x4000) slength <<= ne.neLogicalSectorShiftCount;
1255 if(ulShift >= segpos && ulShift <= segpos + slength) /** we insize segment */
1256 {
1257 RELOC_NE *rne;
1258 CurrSegmentStart = segpos;
1259 CurrSegmentLength = slength;
1260 CurrSegmentHasReloc = (sd.sdFlags >> 8) & 1;
1261 if(!CurrSegmentHasReloc) return RAPREF_NONE;
1262 Direct:
1263 rne = __found_RNE(CurrSegmentStart,CurrSegmentLength,i + 1,(unsigned)(ulShift - CurrSegmentStart),codelen);
1264 if(rne)
1265 {
1266 if(rne->AddrType == 2)
1267 {
1268 rne->ordinal = bmReadWordEx(ulShift,SEEKF_START);
1269 rne->ordinal = __findSpecType(CurrSegmentStart,CurrSegmentLength,i + 1,ulShift,codelen,5,rne->ordinal);
1270 }
1271 if(rne->AddrType == 5)
1272 {
1273 rne->idx = __findSpecType(CurrSegmentStart,CurrSegmentLength,i + 1,ulShift,codelen,2,rne->idx);
1274 }
1275 return BuildReferStrNE(str,(void *)rne,flags,ulShift);
1276 }
1277 else
1278 {
1279 TryLabel:
1280 if(flags & APREF_TRY_LABEL)
1281 {
1282 if(FindPubName(buff,sizeof(buff),r_sh))
1283 {
1284 strcat(str,buff);
1285 if(!DumpMode && !EditMode) GidAddGoAddress(str,r_sh);
1286 return RAPREF_DONE;
1287 }
1288 }
1289 }
1290 return RAPREF_NONE;
1291 }
1292 }
1293 return RAPREF_NONE;
1294 }
1295
1296 /** return False if unsuccess True otherwise */
ReadPubNames(BGLOBAL handle,__filesize_t offset,void (__FASTCALL__ * mem_out)(const char *))1297 static tBool __NEAR__ __FASTCALL__ ReadPubNames(BGLOBAL handle,__filesize_t offset,void (__FASTCALL__ *mem_out)(const char *))
1298 {
1299 struct PubName pnam;
1300 ENTRY ent;
1301 unsigned ord,i = 0;
1302 __filesize_t noff;
1303 tBool ret;
1304 if(!offset) return False;
1305 ret = True;
1306 bioSeek(handle,offset,SEEKF_START);
1307 while(1)
1308 {
1309 unsigned char l;
1310 noff = bioTell(handle);
1311 l = bioReadByte(handle);
1312 if(l == 0 || bioEOF(handle)) { ret = True; break; }
1313 bioSeek(handle,l,SEEKF_CUR);
1314 ord = bioReadWord(handle);
1315 if(ord)
1316 {
1317 if(ReadEntryNE(&ent,ord))
1318 {
1319 pnam.pa = CalcEntryNE(ord,False);
1320 pnam.nameoff = noff;
1321 pnam.attr = SC_GLOBAL;
1322 }
1323 else
1324 {
1325 ret = False;
1326 break;
1327 }
1328 if(pnam.pa)
1329 {
1330 if(!la_AddData(PubNames,&pnam,mem_out))
1331 {
1332 ret = False;
1333 break;
1334 }
1335 }
1336 }
1337 i++;
1338 if(i > 0xFFFD || bioEOF(handle)) { ret = False; break; }
1339 }
1340 return ret;
1341 }
1342
ne_ReadPubName(BGLOBAL b_cache,const struct PubName * it,char * buff,unsigned cb_buff)1343 static void __FASTCALL__ ne_ReadPubName(BGLOBAL b_cache,const struct PubName *it,
1344 char *buff,unsigned cb_buff)
1345 {
1346 unsigned char rlen;
1347 bioSeek(b_cache,it->nameoff,SEEK_SET);
1348 rlen = bioReadByte(b_cache);
1349 rlen = min(rlen,cb_buff-1);
1350 bioReadBuffer(b_cache,buff,rlen);
1351 buff[rlen] = 0;
1352 }
1353
FindPubName(char * buff,unsigned cb_buff,__filesize_t pa)1354 static tBool __NEAR__ __FASTCALL__ FindPubName(char *buff,unsigned cb_buff,__filesize_t pa)
1355 {
1356 return fmtFindPubName(ne_cache2,buff,cb_buff,pa,
1357 ne_ReadPubNameList,
1358 ne_ReadPubName);
1359 }
1360
1361
ne_ReadPubNameList(BGLOBAL handle,void (__FASTCALL__ * mem_out)(const char *))1362 static void __FASTCALL__ ne_ReadPubNameList(BGLOBAL handle,void (__FASTCALL__ *mem_out)(const char *))
1363 {
1364 if((PubNames = la_Build(0,sizeof(struct PubName),mem_out)) != NULL)
1365 {
1366 ReadPubNames(handle,headshift + ne.neOffsetResidentNameTable,mem_out);
1367 ReadPubNames(handle,ne.neOffsetNonResidentNameTable,mem_out);
1368 if(PubNames->nItems)
1369 la_Sort(PubNames,fmtComparePubNames);
1370 }
1371 }
1372
NE_init(void)1373 static void __FASTCALL__ NE_init( void )
1374 {
1375 BGLOBAL main_handle;
1376 PMRegLowMemCallBack(neLowMemFunc);
1377 bmReadBufferEx(&ne,sizeof(NEHEADER),headshift,SEEKF_START);
1378 main_handle = bmbioHandle();
1379 if((ne_cache3 = bioDupEx(main_handle,BBIO_SMALL_CACHE_SIZE)) == &bNull) ne_cache3 = main_handle;
1380 if((ne_cache1 = bioDupEx(main_handle,BBIO_SMALL_CACHE_SIZE)) == &bNull) ne_cache2 = main_handle;
1381 if((ne_cache = bioDupEx(main_handle,BBIO_SMALL_CACHE_SIZE)) == &bNull) ne_cache = main_handle;
1382 if((ne_cache2 = bioDupEx(main_handle,BBIO_SMALL_CACHE_SIZE)) == &bNull) ne_cache2 = main_handle;
1383 }
1384
NE_destroy(void)1385 static void __FASTCALL__ NE_destroy( void )
1386 {
1387 BGLOBAL main_handle;
1388 if(CurrNEChain) { la_Destroy(CurrNEChain); CurrNEChain = 0; }
1389 if(PubNames) { la_Destroy(PubNames); PubNames = 0; }
1390 main_handle = bmbioHandle();
1391 if(ne_cache != &bNull && ne_cache != main_handle) bioClose(ne_cache);
1392 if(ne_cache2 != &bNull && ne_cache2 != main_handle) bioClose(ne_cache2);
1393 if(ne_cache3 != &bNull && ne_cache3 != main_handle) bioClose(ne_cache3);
1394 if(ne_cache1 != &bNull && ne_cache1 != main_handle) bioClose(ne_cache1);
1395 PMUnregLowMemCallBack(neLowMemFunc);
1396 }
1397
NEHelp(void)1398 static __filesize_t __FASTCALL__ NEHelp( void )
1399 {
1400 hlpDisplay(10006);
1401 return BMGetCurrFilePos();
1402 }
1403
neVA2PA(__filesize_t va)1404 static __filesize_t __FASTCALL__ neVA2PA(__filesize_t va)
1405 {
1406 SEGDEF nesd;
1407 tUIntFast16 seg,off;
1408 seg = (va >> 16) & 0xFFFFU;
1409 off = va & 0xFFFFU;
1410 if(!ReadSegDefNE(&nesd,seg)) return 0L;
1411 return nesd.sdOffset ? (((__filesize_t)nesd.sdOffset)<<ne.neLogicalSectorShiftCount) + off : 0;
1412 }
1413
nePA2VA(__filesize_t pa)1414 static __filesize_t __FASTCALL__ nePA2VA(__filesize_t pa)
1415 {
1416 unsigned i,segcount = ne.neSegmentTableCount;
1417 __filesize_t currseg_st,nextseg_st;
1418 for(i = 0;i < segcount-1;i++)
1419 {
1420 SEGDEF nesd_c/*,nesd_n*/;
1421 if(!ReadSegDefNE(&nesd_c,i+1)) return 0L;
1422 currseg_st = (((__filesize_t)nesd_c.sdOffset)<<ne.neLogicalSectorShiftCount);
1423 if(!currseg_st) continue;
1424 /* if(!ReadSegDefNE(&nesd_n,i+2)) goto it_seg;*/
1425 /* nextseg_st = (((unsigned long)nesd_n.sdOffset)<<ne.neLogicalSectorShiftCount);*/
1426 nextseg_st = currseg_st + nesd_c.sdLength;
1427 if(pa >= currseg_st && pa < nextseg_st)
1428 {
1429 /* it_seg:*/
1430 return ((__filesize_t)(i+1) << 16) + (unsigned)(pa - currseg_st);
1431 }
1432 /*
1433 if(i == segcount-2 && pa >= nextseg_st)
1434 return ((__filesize_t)(i+2) << 16) + (unsigned)(pa - nextseg_st);
1435 */
1436 }
1437 return 0L;
1438 }
1439
neGetPubSym(char * str,unsigned cb_str,unsigned * func_class,__filesize_t pa,tBool as_prev)1440 static __filesize_t __FASTCALL__ neGetPubSym(char *str,unsigned cb_str,unsigned *func_class,
1441 __filesize_t pa,tBool as_prev)
1442 {
1443 return fmtGetPubSym(ne_cache,str,cb_str,func_class,pa,as_prev,
1444 ne_ReadPubNameList,
1445 ne_ReadPubName);
1446 }
1447
neGetObjAttr(__filesize_t pa,char * name,unsigned cb_name,__filesize_t * start,__filesize_t * end,int * _class,int * bitness)1448 static unsigned __FASTCALL__ neGetObjAttr(__filesize_t pa,char *name,unsigned cb_name,
1449 __filesize_t *start,__filesize_t *end,int *_class,int *bitness)
1450 {
1451 __filesize_t currseg_st;
1452 unsigned i,segcount = ne.neSegmentTableCount,ret;
1453 unsigned bio_opt;
1454 tBool found;
1455 UNUSED(cb_name);
1456 *start = 0;
1457 *end = bmGetFLength();
1458 *_class = OC_NOOBJECT;
1459 *bitness = DAB_USE16;
1460 name[0] = 0;
1461 ret = 0;
1462 bio_opt = bioGetOptimization(bmbioHandle());
1463 bioSetOptimization(bmbioHandle(),bio_opt | BIO_OPT_DB);
1464 bmSeek((__fileoff_t)headshift + ne.neOffsetSegmentTable,SEEK_SET);
1465 found = False;
1466 for(i = 0;i < segcount;i++)
1467 {
1468 SEGDEF nesd_c;
1469 if(!ReadSegDefNE(&nesd_c,i+1)) return 0L;
1470 currseg_st = (((__filesize_t)nesd_c.sdOffset)<<ne.neLogicalSectorShiftCount);
1471 if(!currseg_st) { *start = *end; continue; } /** BSS segment */
1472 if(pa < currseg_st)
1473 {
1474 *start = *end;
1475 *end = currseg_st;
1476 found = True;
1477 ret = i;
1478 break;
1479 }
1480 if(pa >= currseg_st && pa < currseg_st + nesd_c.sdLength)
1481 {
1482 *start = currseg_st;
1483 *end = *start + nesd_c.sdLength;
1484 *_class = nesd_c.sdFlags & 0x01 ? OC_DATA : OC_CODE;
1485 *bitness = nesd_c.sdFlags & 0x2000 ? DAB_USE32 : DAB_USE16;
1486 ret = i+1;
1487 found = True;
1488 break;
1489 }
1490 *start = currseg_st;
1491 *end = currseg_st + nesd_c.sdLength;
1492 }
1493 if(!found)
1494 {
1495 *start = *end;
1496 *end = bmGetFLength();
1497 }
1498 bioSetOptimization(bmbioHandle(),bio_opt);
1499 return ret;
1500 }
1501
bitnessNE(__filesize_t pa)1502 static int __FASTCALL__ bitnessNE(__filesize_t pa)
1503 {
1504 static __filesize_t st = 0,end = 0;
1505 char name[1];
1506 int _class;
1507 static int bitness;
1508 if(!(pa >= st && pa < end))
1509 {
1510 neGetObjAttr(pa,name,sizeof(name),&st,&end,&_class,&bitness);
1511 }
1512 return bitness;
1513 }
1514
neAddressResolv(char * addr,__filesize_t cfpos)1515 static tBool __FASTCALL__ neAddressResolv(char *addr,__filesize_t cfpos)
1516 {
1517 /* Since this function is used in references resolving of disassembler
1518 it must be seriously optimized for speed. */
1519 tBool bret = True;
1520 tUInt32 res;
1521 if(cfpos >= headshift && cfpos < headshift + sizeof(NEHEADER))
1522 {
1523 strcpy(addr,"NEH :");
1524 strcpy(&addr[5],Get4Digit(cfpos - headshift));
1525 }
1526 else
1527 if(cfpos >= headshift + ne.neOffsetSegmentTable &&
1528 cfpos < headshift + ne.neOffsetSegmentTable + ne.neSegmentTableCount*sizeof(SEGDEF))
1529 {
1530 strcpy(addr,"NESD:");
1531 strcpy(&addr[5],Get4Digit(cfpos - headshift - ne.neOffsetSegmentTable));
1532 }
1533 else
1534 if(cfpos >= headshift + ne.neOffsetEntryTable &&
1535 cfpos < headshift + ne.neOffsetEntryTable + ne.neLengthEntryTable)
1536 {
1537 strcpy(addr,"NEET:");
1538 strcpy(&addr[5],Get4Digit(cfpos - headshift - ne.neOffsetEntryTable));
1539 }
1540 else
1541 if((res=nePA2VA(cfpos))!=0)
1542 {
1543 addr[0] = '.';
1544 strcpy(&addr[1],Get8Digit(res));
1545 }
1546 else bret = False;
1547 return bret;
1548 }
1549
platformNE(void)1550 static int __FASTCALL__ platformNE( void ) { return DISASM_CPU_IX86; }
1551
1552 REGISTRY_BIN neTable =
1553 {
1554 "NE (New Exe)",
1555 { "NEHelp", "ModRef", "ResNam", "NRsNam", NULL, "Entry ", "ResTbl", "NE Hdr", NULL, "SegDef" },
1556 { NEHelp, ShowModRefNE, ShowResNamNE, ShowNResNmNE, NULL, ShowEntriesNE, ShowResourcesNE, ShowNewHeaderNE, NULL, ShowSegDefNE },
1557 IsNEFormat, NE_init, NE_destroy,
1558 NULL,
1559 AppendNERef,
1560 fmtSetState,
1561 platformNE,
1562 bitnessNE,
1563 NULL,
1564 neAddressResolv,
1565 neVA2PA,
1566 nePA2VA,
1567 neGetPubSym,
1568 neGetObjAttr,
1569 NULL,
1570 NULL
1571 };
1572