title: Determine where MZ exe ends, and LE/LX/PE starts
body: <p>I wonder what's the best way to determine where the MZ part of an EXE file ends, and the attached extended executable starts (can be PE/LE/LX/NE/COFF etc ...).</p>
  
  <p>I found this website: <a href="http://www.delorie.com/djgpp/doc/exe/" rel="nofollow">http://www.delorie.com/djgpp/doc/exe/</a> which tries to explain it, but I never get the expected result. I always end up with an offset way beyond the actual PE or LX start offset.</p>
  
  <pre><code>// LXInfo.cpp : Defines the entry point for the console application.
  //
  
  #include "stdafx.h"
  
  struct EXE {
    unsigned short signature; /* == 0x5a4D */
    unsigned short bytes_in_last_block;
    unsigned short blocks_in_file;
    unsigned short num_relocs;
    unsigned short header_paragraphs;
    unsigned short min_extra_paragraphs;
    unsigned short max_extra_paragraphs;
    unsigned short ss;
    unsigned short sp;
    unsigned short checksum;
    unsigned short ip;
    unsigned short cs;
    unsigned short reloc_table_offset;
    unsigned short overlay_number;
  };
  
  struct EXE_RELOC {
    unsigned short offset;
    unsigned short segment;
  };
  
  
  int _tmain(int argc, _TCHAR* argv[])
  {
      struct EXE header1;
      char sFile[]="c:\\register.dll";
      unsigned int extra_data_start;
      char test;
      FILE *fp;
      fp = fopen(sFile, "rb");
      fread(&amp;header1,sizeof(struct EXE),1,fp);
  
      //read the header
      printf("EXE Signature: %x \n", header1.signature);
      printf("Bytes in last block: %08x \n", header1.bytes_in_last_block);
      printf("Blocks in file: %08x \n", header1.blocks_in_file);
      printf("Number of relocations: %08x \n", header1.num_relocs);
      printf("Header paragraphs: %08x \n", header1.header_paragraphs);
      printf("Min. extra paragraphs: %08x \n", header1.min_extra_paragraphs);
      printf("Max. extra paragraphs: %08x \n", header1.max_extra_paragraphs);
      printf("Initial SS value: %08x \n", header1.ss);
      printf("Initial SP value: %08x \n", header1.sp);
      printf("Checksum value: %08x \n", header1.checksum);
      printf("Initial CS value: %08x \n", header1.cs);
      printf("Initial IP value: %08x \n", header1.ip);
      printf("Relocation table offset: %08x \n", header1.reloc_table_offset);
      printf("Overlay number: %x \n", header1.overlay_number);
      printf("\n");
      printf("Start of EXE data: %08x \n", header1.header_paragraphs * 16L);
  
      //calculate end of MZ EXE, according to Delorie
      extra_data_start = header1.blocks_in_file * 512L;
      if (header1.bytes_in_last_block)
          extra_data_start -= (512 - header1.bytes_in_last_block);
  
      printf("End of EXE data: %08x \n", extra_data_start);
  
      // let's read the first two bytes after the MZ EXE data. This should give us a P and E on windows, or L and X on OS/2...
      fseek(fp,extra_data_start,SEEK_SET);
      fread(&amp;test,1,1,fp);
      printf("test char: %c \n", test);
      fread(&amp;test,1,1,fp);
      printf("test char: %c \n", test);
  
      fclose(fp);
      getch();
      return 0;
  }
  </code></pre>