Windows 16-bit Executable(NE.rfi):
Class: Executable and Object, Status: Almost Complete, Last change: 08.03.2008 14:47:30

type

DWORD ulong

TNEExeType enum byte (
  NE_UNKNOWN=0x0,         /* Unknown (any "new-format" OS) */
  NE_OS2=0x1,     /* Microsoft/IBM OS/2 (default)  */
  NE_WINDOWS=0x2,         /* Microsoft Windows */
  NE_DOS4=0x3,    /* Microsoft MS-DOS 4.x */
  NE_WIN386=0x4   /* Windows 386  ????????? */
)

TSegTable(Cnt) forward
PSegTable(Cnt) ^TSegTable(@:Cnt) - NewHdrOfs near=word

TEntryTbl(Sz) forward
PEntryTbl(Sz) ^TEntryTbl(@:Sz) - NewHdrOfs near=word;

TResTable(Sz) forward
PResTable(Sz) ^TResTable(@:Sz) - NewHdrOfs nil:(@:Sz<=4) near=word

TResidentNames forward
PResidentNames ^TResidentNames - NewHdrOfs near=word
PNonResidentNames ^TResidentNames near=ulong

TModuleRefTbl(Cnt) forward
PModuleRefTbl(Cnt) ^TModuleRefTbl(@:Cnt) - NewHdrOfs near=word


TNEFlags set 16 of (
  NENOTP = 15,    //0x8000        /* Not a process */
  NEIERR = 13,    //0x2000        /* Errors in image */
  NEBOUND = 11,   //0x0800        /* Bound as family app */
// NEAPPTYP       0x0700          /* Application type mask */
// NENOTWINCOMPAT  0x0100         /* Not compatible with P.M. Windowing */
// NEWINCOMPAT    0x0200          /* Compatible with P.M. Windowing */
// NEWINAPI       0x0300          /* Uses P.M. Windowing API */
  NEFLTP = 7,     //0x0080        /* Floating-point instructions */
  NEI386 = 6,     //0x0040        /* 386 instructions */
  NEI286 = 5,     //0x0020        /* 286 instructions */
  NEI086 = 4,     //0x0010        /* 8086 instructions */
  NEPROT = 3,     //0x0008        /* Runs in protected mode only */
  NEPPLI = 2,     //0x0004        /* Per-Process Library Initialization */
  NEINST = 1,     //0x0002        /* Instance data */
  NESOLO = 0      //0x0001        /* Solo data */
)

TNEHdr struc
  byte  ne_ver           /* 02 Linker Version number */
  byte  ne_rev           /* 03 Linker Revision number */
  PEntryTbl ne_enttab    /* 04 Offset of Entry Table */
  word  ne_cbenttab      /* 06 Number of bytes in Entry Table */
  ulong ne_crc           /* 08 Checksum of whole file */
  TNEFlags  ne_flags     /* 0C Flag word */
  word  ne_autodata      /* 0E Automatic data segment number */
  word  ne_heap          /* 10 Initial heap allocation */
  word  ne_stack         /* 12 Initial stack allocation */
  ulong ne_csip          /* 14 Initial CS:IP setting */
  ulong ne_sssp          /* 18 Initial SS:SP setting */
  int   ne_cseg          /* 1C Count of file segments */
  int   ne_cmod          /* 1E Entries in Module Reference Table */
  word  ne_cbnrestab     /* 20 Size of non-resident name table */
  PSegTable(@.ne_cseg) ne_segtab /* 22 Offset of Segment Table */
  PResTable ne_rsrctab   /* 24 Offset of Resource Table */
  PResidentNames ne_restab /* 26 Offset of resident name table */
  PModuleRefTbl(@.ne_cmod) ne_modtab /* 28 Offset of Module Reference Table */
  word  ne_imptab        /* 2A Offset of Imported Names Table */
  PNonResidentNames ne_nrestab /* 2C Offset of Non-resident Names Table */
  int   ne_cmovent       /* 30 Count of movable entries */
  word  ne_align         /* 32 Segment alignment shift count */
  int   ne_cres          /* 34 Count of resource entries */
  TNEExeType ne_exetyp   /* 36 Target operating system */
  byte  ne_addflags      /* 37 Additional flags */
  array[3] of word ne_res/* 38 3 reserved words */
  byte  ne_sdkrev        /* 3E Windows SDK revison number */
  byte  ne_sdkver        /* 3F Windows SDK version number */
ends:[@.ne_enttab:Sz=@.ne_cbenttab,
  @.ne_rsrctab:Sz=@.ne_restab-@.ne_rsrctab]

data

NewHdrOfs+2 TNEHdr NEHdr

const
  SectorSize = (1 shl NEHdr.ne_align)/*512*/;

  NSTYPE     =     0x0007;  /* Segment type mask */
  NSCODE     =     0x0000;  /* Code segment */
  NSDATA     =     0x0001;  /* Data segment */
  NSITER     =     0x0008;  /* Iterated segment flag */
  NSMOVE     =     0x0010;  /* Movable segment flag */
  NSSHARED   =     0x0020;  /* Shared segment flag */
  NSPRELOAD  =     0x0040;  /* Preload segment flag */
  NSEXRD     =     0x0080;  /* Execute-only (code segment), or
                           *  read-only (data segment)
                           */
  NSRELOC    =     0x0100;  /* Segment has relocations */
  NSCONFORM  =     0x0200;  /* Conforming segment */
  NSDPL      =     0x0C00;  /* I/O privilege level (286 DPL bits) */
  SHIFTDPL   =     10;      /* Left shift count for SEGDPL field */
  NSDISCARD  =     0x1000;  /* Segment is discardable */
  NS32BIT    =     0x2000;  /* 32-bit code segment */
  NSHUGE     =     0x4000;  /* Huge memory segment, length of
                           * segment and minimum allocation
                           * size are in segment sector units
                           */
  NSPURE     =     NSSHARED;  /* For compatibility */

  NSLOADED  =  0x0004;     /* ns_sector field contains memory addr */

type
//Segment flags
TSegFlags set 16 of (
  DATA     =     0,  /* Data segment */
  Allocated=     1,  /* loader has allocated memory for segment */
  LOADED   =     2,  /* ns_sector field contains memory addr */
  ITER     =     3,  /* Iterated segment flag */
  MOVE     =     4,  /* Movable segment flag */
  SHARED   =     5,  /* Shared segment flag */
  PRELOAD  =     6,  /* Preload segment flag */
  EXRD     =     7,  /* Execute-only (code segment), or
                           *  read-only (data segment)
                           */
  RELOC    =     8,  /* Segment has relocations */
  CONFORM  =     9,  /* Conforming segment */
//  DPL      =     0x0C00,  /* I/O privilege level (286 DPL bits) */
  DISCARD  =     12,  /* Segment is discardable */
  IS32BIT  =     13,  /* 32-bit code segment */
  HUGE     =     14  /* Huge memory segment, length of
                           * segment and minimum allocation
                           * size are in segment sector units
                           */
)

type

TSegNDX enum Byte (
  bSegMovable=0xFF,
  bModuleConstant=0xFE
)


TIterSegData struc
  word NIter
  word Sz
  raw[@.Sz] IterDat
ends

/** relocation-address types: **/
TReloAddrType enum byte (
  raLowB=0,  //Low byte at the specified offset
  ra16sel=2, //16-bit selector
  ra32ptr=3, //32-bit pointer
  ra16ofs=5, //16-bit offset
  ra48ptr=11,//48-bit pointer
  ra32ofs=13 //32-bit offset
)

/** relocation types: **/

TReloType enum byte (
  rtIntrRef=0, //Internal reference
  rtImpOrd=1,  //Imported ordinal
  rtImpName=2, //Imported name
  rtOSFIXUP=3,  //OSFIXUP
  rtIntrRefA=4, //Internal reference
  rtImpOrdA=5,  //Imported ordinal
  rtImpNameA=6, //Imported name
  rtOSFIXUPA=7  //OSFIXUP
)

TIntrRef struc
  TSegNDX hSeg
  Byte B0
  case @.hSeg of
    bSegMovable: int //ordinal in the segment's entry table
  else word //TgtOfs
  endc Tgt
ends

TImpOrd struc
  int hMod
  int hOrd
ends

TImpName struc
  int hMod
  word NameOfs
ends

TOSFIXUP struc
  word W0
  word W1
ends

TReloRec struc
  TReloAddrType AT
  TReloType RT
  word Ofs
  case @.RT of
    rtIntrRef,rtIntrRefA: TIntrRef
    rtImpOrd,rtImpOrdA: TImpOrd
    rtImpName,rtImpNameA: TImpName
    rtOSFIXUP,rtOSFIXUPA: TOSFIXUP
  endc Inf
ends

TReloInfo struc
  int Cnt
  array[@.Cnt] of TReloRec Tbl
ends

TSegData(Sz,Flags) struc
  case @:Flags and NSITER of
   0: raw[@@:Sz]
  else TIterSegData
  endc dat
  case @:Flags and NSRELOC of
    NSRELOC: TReloInfo
  endc ReloTbl
ends

PSegData(Sz,Flags) ^TSegData(@:Sz,@:Flags) * SectorSize near=word

TNewSegRec struc /* New .EXE segment table entry */
  PSegData  ns_sector    /* File sector of start of segment */
  word      ns_cbseg     /* Number of bytes in file */
  TSegFlags ns_flags     /* Attribute flags */
  word      ns_minalloc  /* Minimum allocation in bytes */
ends :[@.ns_sector:Sz=(0x10000 when (@.ns_cbseg=0)) exc @.ns_cbseg,
  @.ns_sector:Flags = @.ns_flags]

TSegTable(Cnt) array[@:Cnt] of TNewSegRec


/*** Entry Table ***/

TMovableSegData struc
  Byte Flags //Specifies a byte value. This value can be a
             //combination of the following bits:
             //Bit(s)    Meaning
             //0     If this bit is set, the entry is exported.
             //1     If this bit is set, the segment uses a global
             //    (shared) data segment.
             //3-7   If the executable file contains code that
             //    performs ring transitions, these bits specify
             //    the number of words that compose the stack. At
             //    the time of the ring transition, these words
             //    must be copied from one ring to the other.
  Word Int3F //Specifies an int 3fh instruction.
  Byte hSeg  //Specifies the segment number.
  Word Ofs   //Specifies the segment offset.
ends

TFixedSegData struc
  Byte Flags //Specifies a byte value. This value can be a
             //combination of the following bits:
             //Bit(s)    Meaning
             //0     If this bit is set, the entry is exported.
             //1     If this bit is set, the entry uses a global
             //  (shared) data segment. (This may be set only
             //  for SINGLEDATA library modules.)
             //3-7   If the executable file contains code that
             //  performs ring transitions, these bits specify
             //  the number of words that compose the stack. At
             //  the time of the ring transition, these words
             //  must be copied from one ring to the other.
  Word Ofs   //Specifies an offset.
ends

TEntryRec(hSeg) case TSegNDX @:hSeg of
  bSegMovable: TMovableSegData
else TFixedSegData
endc

TEntryBundleTbl0(Cnt,hSeg) array[@:Cnt] of TEntryRec(@:hSeg)

TEntryBundleTbl(Cnt,hSeg,hSeg1) case @:hSeg of
  0: void //Experimental fact
else TEntryBundleTbl0(@:Cnt,@:hSeg1)
endc

TEntryBundle struc
  Byte Cnt
  TSegNDX hSeg
  TEntryBundleTbl(@.Cnt,@.hSeg,@.hSeg) Tbl
ends

//TEntryTbl(Sz) raw[@:Sz]
TEntryTbl(Sz) array of TEntryBundle ? @.Cnt=0!Byte; :[@:Size=@:Sz]

/*** Resident Names Table ***/

TResidentNameInf struc
  str N
  int Id
ends

TResidentNames array of TResidentNameInf ?@.N[0]=0!byte;

/*** Module Reference Table ***/

TModuleRefTbl(Cnt) array[@:Cnt] of Word

/*** Imported Names Table ***/

//TImpNamesTbl

/*** Resources ***/

const

RsrcOfs = NEHdr.ne_rsrctab+NewHdrOfs;

type

PRsrcName ^str - RsrcOfs hideref nil:(@ and 0x8000<>0) near=word:
  displ=(@^,'{',@,'}')

TRsrcTypeID enum PRsrcName (
  rt_Cursor      = 0x8001,
  rt_Bitmap      = 0x8002,
  rt_Icon        = 0x8003,
  rt_Menu        = 0x8004,
  rt_Dialog      = 0x8005,
  rt_String      = 0x8006,
  rt_FontDir     = 0x8007,
  rt_Font        = 0x8008,
  rt_Accelerator = 0x8009,
  rt_RCData      = 0x800A,
  rt_Group_Cursor= 0x800C,
  rt_Group_Icon  = 0x800E,
  rt_Version = 0x8010
)

TNAMEINFO(Tp) forward

TTYPEINFO struc
  TRsrcTypeID rtTypeID
  int         rtResourceCount
  DWORD       rtReserved
  array[@.rtResourceCount] of TNAMEINFO(@@.rtTypeID) rtNameInfo
ends

TResTbl array of TTYPEINFO ?@.rtTypeID=0!WORD;

TResNames array of str ?@[0]=0;

TResTable(Sz) struc
  WORD rscAlignShift
  TResTbl rscTypes
  TResNames rscNames
ends:[@:Size=@:Sz]

const
  resAlign=(1 shl NEHdr.ne_rsrctab^.rscAlignShift)exc 0;

include verres16.rfi

type

TResData(Sz,Tp) struc
  case TRsrcTypeID @:Tp of
    rt_Version: TResVersion
  endc Inf
  raw[] rest
ends:[@:Size=@:Sz]

PResData(Sz,Tp) ^TResData(@:Sz,@:Tp) * resAlign near=word

TNAMEINFO(Tp) struc
  PResData(Tp=@:Tp) rnOffset
  WORD rnLength
  WORD rnFlags
  PRsrcName rnID
  WORD rnHandle
  WORD rnUsage
ends:[@.rnOffset:Sz=@.rnLength * resAlign]

autoname

TTYPEINFO .rtTypeID _El


Other specifications.


FlexT home page, Author`s home page.