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