[Back to FILES SWAG index] [Back to Main SWAG index] [Original]

    ===========================================================================
     BBS: Canada Remote Systems
    Date: 07-03-93 (11:56)             Number: 29412
    From: KELD R. HANSEN               Refer#: NONE
      To: JON JASIUNAS                  Recvd: NO
    Subj: Re: Self-modifying .EXEs       Conf: (1221) F-PASCAL
    ---------------------------------------------------------------------------
    In a message dated 28 Jun 93, Jon Jasiunas (1:273/216.0) wrote:

     > Here's the code I use for my self-modifying .EXEs.  I've used it
     > successfully in several applications.

    It works fine (I have one similar of my own), but it doesn't take care of DPMI
    programs and won't work if your "customer" PKLITEs the program.

    TYPE
      ExeHeaderDOS          = RECORD
                    { 00 }      Signature           : ARRAY[1..2] OF CHAR;
                    { 02 }      LastPageSize        : WORD;
                    { 04 }      Pages               : WORD;
                    { 06 }      RelocItems          : WORD;
                    { 08 }      HeaderSizePara      : WORD;
                    { 0A }      MinMemPara          : WORD;
                    { 0C }      MaxMemPara          : WORD;
                    { 0E }      EntrySS             : WORD;
                    { 10 }      EntrySP             : WORD;
                    { 12 }      CheckSum            : WORD;
                    { 14 }      EntryIP             : WORD;
                    { 16 }      EntryCS             : WORD;
                    { 18 }      FirstRelocItemOfs   : WORD;
                    { 1A }      OverlayNumber       : WORD;
                                Reserved            : ARRAY[$1C..$23] OF BYTE;
                    { 24 }      IdentifierOEM       : WORD;
                    { 26 }      InformationOEM      : WORD;
                                ReservedToo         : ARRAY[$28..$3B] OF BYTE;
                    { 3C }      NewExeHeaderOfs     : LONGINT
                              END;
      ExeHeaderOS2          = RECORD
                                Signature           : ARRAY[1..2] OF CHAR;
                                LinkerMajorVers     : BYTE;
                                LinkerMinorVers     : BYTE;
                                EntryTableOfs       : WORD;
                                EntryTableSize      : WORD;
                                CRC                 : LONGINT;
                                ModuleFlags         : WORD;
                                SegmentNoDGROUP     : WORD;
                                HeapSize            : WORD;
                                StackSize           : WORD;
                                EntryIP             : WORD;
                                EntryCS             : WORD;
                                EntrySP             : WORD;
                                EntrySS             : WORD;
                                SegmentTableEntries : WORD;
                                ModuleRefEntries    : WORD;
                                NonResNameTableSize : WORD;
                                SegTableOfs         : WORD;
                                ResourceTableOfs    : WORD;
                                ResNamesTableOfs    : WORD;
                                ModuleRefTableOfs   : WORD;
                                ImpNamesTableOfs    : WORD;
                                NonResNamesTableOfs : LONGINT;
                                MovableEntryPoints  : WORD;
                                AlignmentUnitPower  : WORD;
                                ResourceTableEntries: WORD;
                                TargetOS            : BYTE;
                                WindowsFlags        : BYTE;
                                FastLoadStart       : WORD;
                                FastLoadSize        : WORD;
                                Reserved            : WORD;
                                WindowsVers         : WORD
                              END;
      SegTableRec           = RECORD
                                Start               : WORD;
                                Size                : WORD;
                                Flags               : WORD;
                                MinSize             : WORD
                              END;
      FileOffset            = LONGINT;

    PROCEDURE ReadOnly;
      INLINE($C6/$06/FileMode/$A0);

    PROCEDURE ReadWrite;
      INLINE($C6/$06/FileMode/$02);

    { ExeOfs returns the offset of the item V in the .EXE file of the currently   }
    { running program. Use this to get the offset of a configuration record that  }
    { is located in the .EXE file (remember that you must declare it as a typed   }
    { constant to include it in the .EXE file)                                    }

    {$IFDEF DPMI }
    FUNCTION ExeOfs(CONST V) : FileOffset;
      VAR
        HeaderDOS   : ExeHeaderDOS;
        HeaderOS2   : ExeHeaderOS2;
        FIL         : FILE;
        CodeSeg,Seg : WORD;
        SegTab      : SegTableRec;

      BEGIN
        ReadOnly;
        ASSIGN(FIL,ParamStr(0)); RESET(FIL,1);
        BLOCKREAD(FIL,HeaderDOS,SizeOf(ExeHeaderDOS));
        IF HeaderDOS.Signature<>'MZ' THEN
          ExeOfs:=-1
        ELSE BEGIN
          SEEK(FIL,HeaderDOS.NewExeHeaderOfs);
          BLOCKREAD(FIL,HeaderOS2,SizeOf(ExeHeaderOS2));
          IF HeaderOS2.Signature<>'NE' THEN
            ExeOfs:=-1
          ELSE BEGIN
            ASM
                    MOV     BX,WORD PTR V+2
                    MOV     CX,SS
                    CMP     BX,CX
                    JE      @STACK
                    XOR     AX,AX
                    VERW    BX
                    JZ      @OUT
                    MOV     ES,BX
                    MOV     AX,ES:[0000h]
                    JMP     @OUT
            @STACK: MOV     AX,HeaderOS2.EntrySS
            @OUT:   MOV     CodeSeg,AX
            END;
            IF CodeSeg<>0 THEN BEGIN
              SEEK(FIL,HeaderDOS.NewExeHeaderOfs+HeaderOS2.SegTableOfs+
                PRED(CodeSeg)*SizeOf(SegTableRec));
              BLOCKREAD(FIL,SegTab,SizeOf(SegTableRec)) END
            ELSE BEGIN
              SEEK(FIL,HeaderDOS.NewExeHeaderOfs+HeaderOS2.SegTableOfs);
              FOR Seg:=1 TO HeaderOS2.SegmentTableEntries DO BEGIN
                BLOCKREAD(FIL,SegTab,SizeOf(SegTableRec));
                IF (SegTab.Start>0) AND (SegTab.Flags AND $0001=$0001) THEN BREAK
              END
            END;
            ExeOfs:=SegTab.Start SHL HeaderOS2.AlignmentUnitPower+OFS(V)
          END
        END;
        CLOSE(FIL);
        ReadWrite
      END;
    {$ELSE }
    FUNCTION ExeOfs(CONST V) : FileOffset;
      VAR
        HeaderDOS   : ExeHeaderDOS;
        FIL         : FILE;

      BEGIN
        ReadOnly;
        ASSIGN(FIL,ParamStr(0)); RESET(FIL,1);
        BLOCKREAD(FIL,HeaderDOS,SizeOf(ExeHeaderDOS));
        CLOSE(FIL);
        ExeOfs:=(HeaderDOS.HeaderSizePara+(SEG(V)-(PrefixSeg+$0010)))*16+OFS(V)
      END;
    {$ENDIF }

[Back to FILES SWAG index] [Back to Main SWAG index] [Original]