//                                                                           

//  Copyright (c) 1998, 1999, 2000, 2001, 2002, Intel Corporation            

//  All rights reserved.                                                     

//                                                                           

//  WARRANTY DISCLAIMER                                                      

//                                                                           

//  THESE MATERIALS ARE PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   

//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT        

//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR    

//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS      

//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,    

//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,      

//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR       

//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY      

//  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING   

//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THESE      

//  MATERIALS, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.            

//                                                                           

//  Intel Corporation is the author of the Materials, and requests that all  

//  problem reports or change requests be submitted to it directly at        

//  http:                                                                   //developer.intel.com/opensource.                                   

//                                                                           

//

//-------------------------------------------------------------------------------

//-------------------------------------------------------------------------------

//

#include "pe32.h"

#include <sys/types.h>

#include <time.h>

#include "endianess.h"

//  a structure that is used to hold all available sections and sort them

//  by virtual address                                                    

struct sec_vlist {

    PE32_section_object *sec;

    PE32_vaddr vaddr;

};

struct sg_vlist {

    PE32_secgrp_object *sg;

    PE32_vaddr vaddr;

};

static FUNC mfl_err PE32_write_pe_file_header (PE32_file_object *fod);

#ifdef PECOFF32_EM

static FUNC mfl_err PE32_64_write_pe_file_header (PE32_file_object *fod);

#endif

static FUNC mfl_err PE32_prepare_PE32_sections_and_write (PE32_file_object *fod);

static FUNC mfl_err PE32_write_one_coff_sec_content (PE32_file_object *pfobj,

                                                PE32_section_object *psecobj);

static FUNC mfl_err PE32_write_pe_sections (PE32_file_object *fod);

static FUNC mfl_err PE32_write_pe_section_header

    (PE32_file_object *fod, struct sg_vlist *secl);

static FUNC mfl_err PE32_write_internal_hdr (PE32_file_object *fod,

                                             int internal, ULONG charac,

                                             PE32_offset *file_ptr);

static FUNC mfl_err PE32_write_pe_section_content

    (PE32_file_object *fod, struct sg_vlist *secl);

static FUNC mfl_err PE32_write_basereloc (PE32_file_object *fod,

                                          struct sg_vlist *secl);

static FUNC mfl_err PE32_write_export_symbols (PE32_file_object *fod);

static FUNC mfl_err PE32_write_import_symbols (PE32_file_object *fod);

static FUNC mfl_err PE32_write_file_pad_align (PE32_file_object *fod,

                                               PE32_offset *file_ptr,

                                               PE32_align align);

static FUNC mfl_err PE32_write_file_pad_offset (PE32_file_object *fod,

                                                PE32_offset file_ptr,

                                                PE32_offset offset);

static FUNC mfl_err PE32_open_for_write (PE32_file_object *fod, mfl_str name);

static FUNC mfl_err PE32_calculate_image_size (PE32_file_object *pfobj);

static FUNC mfl_err PE32_prepare_coff_file_for_write (PE32_file_object *pfobj);

static FUNC mfl_err PE32_write_coff_file_header (PE32_file_object *pfobj);

static FUNC mfl_err PE32_write_coff_sec_header (PE32_file_object *pfobj);

static FUNC mfl_err PE32_write_coff_sec_content (PE32_file_object *pfobj);

static FUNC mfl_err PE32_write_coff_symtab_strtab (PE32_file_object *pfobj);

//---------------------------------------------------------------------------

// -                         PE32_write_file                                  -

// -                                                                          -

// - Write function for pe32 files                                            -

// ---------------------------------------------------------------------------

FUNC mfl_err PE32_write_file (mfl_str name, mfl_od od)

{

    mfl_err error;

    PE32_file_object *fod;

    mfl_file_type file_type;

    fod = (PE32_file_object *)od;

    if ((error = PE32_open_for_write (fod, name)) != MFL_OK)

      return error;

    if (fod->mflfh.name != NULL)

        mfl_free (fod->mflfh.name);

    if ((fod->mflfh.name = mfl_malloc(strlen(name) +1)) == NULL)

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    strcpy(fod->mflfh.name, name);

    if ((error = PE32_get_file_type(od,MFL_PROP_FILE_TYPE,NULL,&file_type)) != MFL_OK)

        return error;

    if (file_type == MFL_FILE_TYPE_DYN_EXEC || file_type == MFL_FILE_TYPE_SHARED)

    {

        if ((error = PE32_prepare_PE32_sections_and_write(fod)) != MFL_OK)

           return error;

        //

//        if ((error = PE32_write_pe_file_header (fod)) != MFL_OK)

//            return error;

//

//        if ((error = PE32_prepare_section_for_write(fod)) != MFL_OK) {

//            return error;

//        }

//

//        if ((error = PE32_translate_coff_symtabs(pfobj)) != MFL_OK) {

//            return error;

//        }

//

//        if ((error = PE32_write_pe_sections (fod)) != MFL_OK)

//           return error;

//        

        if ((error = PE32_write_coff_symtab_strtab(fod)) != MFL_OK)

           return error;

     }

     else

     {

        //  Write Coff OMF file (relocatble files only )

        if (file_type == MFL_FILE_TYPE_RELOC)

        {

            if ((error = PE32_prepare_coff_file_for_write(fod)) != MFL_OK)

               return error;

            if ((error = PE32_write_coff_file_header(fod)) != MFL_OK)

               return error;

            if ((error = PE32_write_coff_sec_header(fod)) != MFL_OK)

               return error;

            if ((error = PE32_write_coff_sec_content(fod)) != MFL_OK)

               return error;

            if ((error = PE32_write_coff_symtab_strtab(fod)) != MFL_OK)

               return error;

        }

        else

          //  In the case of non support write file type

          return MFL_ERR_INV_FILE_TYPE;

     }

    return MFL_OK;

}

static FUNC int cmpvv (const void *v1, const void *v2)

{

    return ((struct sec_vlist *)v1)->vaddr - ((struct sec_vlist *)v2)->vaddr;

}

//-----------------------------------------------------------------------------

// -                      PE32_prepare_PE32_sections_and_write                  -

// - Prepare the PE32 file for writing and calculate the total size of the file

// - and the final place of all the tables (relocation tables symbol table and

// - string table).  Very similar to the PE32_prepare_coff_file_for_write.

// - The only difference is that the sections are sorted by their virtual addr,

// - and the section size is put into Ish->Misc.VirtualSize field of the section.

// -----------------------------------------------------------------------------

static FUNC mfl_err PE32_prepare_PE32_sections_and_write (PE32_file_object *pfobj)

{

    mfl_err              error;

    mfl_32size           file_size, sec_size, aligned_sec_size;

    PE32_section_object  *psecobj;

    struct sec_vlist *scl;

    unsigned int i, sec_ind, sec_num, total_num_sec;

    //  create new COFF string table

    if ((error = PE32_strtab_init(pfobj)) != MFL_OK) {

        return error;

    }

    //  Build Coff symbol table and string table

    if ((error = PE32_translate_coff_symtabs(pfobj)) != MFL_OK) {

        return error;

    }

    //  build the sections list

    sec_num = 0;

    total_num_sec = 0;

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END)

     {

        total_num_sec++;

        if (PE32_is_sec_mem_expand(psecobj) == FALSE)

            sec_num++;

        else

            //  In the case of .bss section

            psecobj->Ish->PointerToRawData = 0;

     }

    sec_size = 0;

    file_size = pfobj->doshdr.e_lfanew +

                sizeof(pfobj->nthdr.Signature) +

                sizeof(IMAGE_FILE_HEADER) +

                pfobj->nthdr.FileHeader.SizeOfOptionalHeader;

    pfobj->nthdr.FileHeader.NumberOfSections = total_num_sec;

    file_size += total_num_sec * IMAGE_SIZEOF_SECTION_HEADER;

  if (sec_num > 0)

   {

    if ((scl = mfl_malloc(sec_num * sizeof(struct sec_vlist))) == NULL) {

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    }

    sec_ind = 0;

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END)

     {

        if (PE32_is_sec_mem_expand(psecobj) == FALSE) {

            scl[sec_ind].sec = psecobj;

            scl[sec_ind].vaddr = PE32_section_vaddr(psecobj);

            sec_ind++;

        }

     }

    qsort(scl, sec_num, sizeof(struct sec_vlist), cmpvv);

    for (i=0; i< sec_num; i++)

     {

      psecobj = scl[i].sec;

      psecobj->Ish->PointerToRawData = file_size;

      file_size += PE32_section_size(psecobj);

      // In sco the section get virtualAddress is the place of the section

//        in the file.

      if (pfobj->mflfh.company_style == MFL_COMP_STYLE_MICROFOCUS) {

            psecobj->Ish->VirtualAddress = sec_size;

        }

      aligned_sec_size = (PE32_section_size(psecobj) +

                          PE32_section_alignment(psecobj) - 1) &

                        ~(PE32_section_alignment(psecobj) - 1);

      psecobj->Ish->Misc.VirtualSize = PE32_section_size(psecobj);

      sec_size += PE32_section_size(psecobj);

      //  Transfer MOFL relocation table to COFF table and update the

      //  relocation addend inside the section raw content.           

#ifdef PECOFF32_EM

      if (pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE ||

          pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432) {

            if ((error = PE32_trans_mofl_to_tahoe_reloc(psecobj)) != MFL_OK) {

                return error;

            }

        } else

#endif                                                                      //  PECOFF32_EM

        if ((error = PE32_trans_mofl_to_reloc(psecobj,

                    pfobj->nthdr.FileHeader.Machine)) != MFL_OK) {

            return error;

        }

      //  Prepare for lineinfo

      if ((error = PE32_prepare_lineinfo_for_write(psecobj)) != MFL_OK) {

            return error;

      }

      if (psecobj->Ish->NumberOfLinenumbers > 0)

       {

        psecobj->Ish->PointerToLinenumbers = file_size;

        file_size += psecobj->Ish->NumberOfLinenumbers * IMAGE_SIZEOF_LINENUMBER;

       }

      else

       {

        psecobj->Ish->PointerToLinenumbers = 0;

       }

     }

   }

    //  compute data offset for the remaining sections

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END)

     {

      if (PE32_is_sec_mem_expand(psecobj) == FALSE)

        continue;

      psecobj->Ish->PointerToRawData = file_size;

      file_size += PE32_section_size(psecobj);

      // In sco the section get virtualAddress is the place of the section

//        in the file.

      if (pfobj->mflfh.company_style == MFL_COMP_STYLE_MICROFOCUS) {

            psecobj->Ish->VirtualAddress = sec_size;

        }

      aligned_sec_size = (PE32_section_size(psecobj) +

                          PE32_section_alignment(psecobj) - 1) &

                        ~(PE32_section_alignment(psecobj) - 1);

      psecobj->Ish->Misc.VirtualSize = PE32_section_size(psecobj);

      sec_size += PE32_section_size(psecobj);

      //  Transfer MOFL relocation table to COFF table and update the

      //  relocation addend inside the section raw content.           

#ifdef PECOFF32_EM

      if (pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE ||

          pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432) {

            if ((error = PE32_trans_mofl_to_tahoe_reloc(psecobj)) != MFL_OK) {

                return error;

            }

        } else

#endif                                                                      //  PECOFF32_EM

        if ((error = PE32_trans_mofl_to_reloc(psecobj,

                        pfobj->nthdr.FileHeader.Machine)) != MFL_OK) {

            return error;

        }

      //  Prepare for lineinfo

      if ((error = PE32_prepare_lineinfo_for_write(psecobj)) != MFL_OK) {

            return error;

      }

      if (psecobj->Ish->NumberOfLinenumbers > 0)

       {

        psecobj->Ish->PointerToLinenumbers = file_size;

        file_size += psecobj->Ish->NumberOfLinenumbers * IMAGE_SIZEOF_LINENUMBER;

       }

      else

       {

        psecobj->Ish->PointerToLinenumbers = 0;

       }

     }

    //  Update the Value field of all the define symbol in any section

    if ((error = PE32_update_coff_symbol(pfobj)) != MFL_OK) {

        return error;

    }

    pfobj->nthdr.FileHeader.PointerToSymbolTable = file_size;

    file_size += pfobj->nthdr.FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL;

    file_size += pfobj->str_size;

    //  write the file

    //  first, the header

    if ((error = PE32_write_pe_file_header (pfobj)) != MFL_OK)

        return error;

    //  now, write the section headers

    if ((error = PE32_write_coff_sec_header(pfobj)) != MFL_OK)

       return error;

    //  write the sections themselves

    for (i=0; i< sec_num; i++)

     {

      psecobj = scl[i].sec;

      if ((error = PE32_write_one_coff_sec_content(pfobj, psecobj)) != MFL_OK)

        return error;

     }

    //  write the remaining sections

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END)

     {

      if (PE32_is_sec_mem_expand(psecobj) == FALSE)

        continue;

      if ((error = PE32_write_one_coff_sec_content(pfobj, psecobj)) != MFL_OK)

        return error;

     }

    if (scl)

     {

        mfl_free(scl);

        scl = 0;

     }

    return MFL_OK;

}

//-------------------------------------------------------------------------------------

// -                          PE32_prepare_coff_file_for_write                          -

// - Prepare the Coff file for writing and calculate the total size of the file and the -

// - final place of all the tables (relocation tables symbol table and string table ).  -

// -------------------------------------------------------------------------------------

static FUNC mfl_err PE32_prepare_coff_file_for_write (PE32_file_object *pfobj)

{

    mfl_err              error;

    mfl_32size           file_size, sec_size;

    PE32_section_object  *psecobj;

    //  create new COFF string table

    if ((error = PE32_strtab_init(pfobj)) != MFL_OK) {

        return error;

    }

    //  Build the Coff section list

    if ((error = PE32_prepare_section_for_write(pfobj)) != MFL_OK) {

        return error;

    }

    //  Build Coff symbol table and string table

    if ((error = PE32_translate_coff_symtabs(pfobj)) != MFL_OK) {

        return error;

    }

    //  Find the file size and the symbol table place

    file_size = IMAGE_SIZEOF_FILE_HEADER;

    file_size += pfobj->nthdr.FileHeader.NumberOfSections * IMAGE_SIZEOF_SECTION_HEADER;

    sec_size = 0;

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj))

           != MFL_OD_END) {

        if (PE32_is_sec_mem_expand(psecobj) == FALSE) {

            psecobj->Ish->PointerToRawData = file_size;

            file_size += PE32_section_size(psecobj);

        } else {

            //  In the case of .bss section

            psecobj->Ish->PointerToRawData = 0;

        }

        //  In sco the section get virtualAddress is the place of the section in the file.

        if (pfobj->mflfh.company_style == MFL_COMP_STYLE_MICROFOCUS) {

            psecobj->Ish->VirtualAddress = sec_size;

        }

        psecobj->Ish->Misc.VirtualSize = 0;

#if 0

        psecobj->Ish->Misc.PhysicalAddress = sec_size;

#endif                                                                      //  0

        sec_size += PE32_section_size(psecobj);

        //  Transfer MOFL relocation table to COFF table and update the

        //  relocation addend inside the section raw content.           

#ifdef PECOFF32_EM

        if (pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE ||

            pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432) {

            if ((error = PE32_trans_mofl_to_tahoe_reloc(psecobj)) != MFL_OK) {

                return error;

            }

        } else

#endif                                                                      //  PECOFF32_EM

        if ((error = PE32_trans_mofl_to_reloc(psecobj,

                        pfobj->nthdr.FileHeader.Machine)) != MFL_OK) {

            return error;

        }

    //  In the GNT architecture the section raw content should come in one piece.

    //  Set the pointer of the relocation table in the output file.

    if (mfl_od_omf(pfobj) != MFL_OMF_GNT32)

     {

      mfl_rel_num num_of_relocs = psecobj->relocations_num;

      if (num_of_relocs > 0)

       {

        psecobj->Ish->PointerToRelocations = file_size;

        file_size += num_of_relocs * IMAGE_SIZEOF_RELOCATION;

        if (num_of_relocs > USHRT_MAX)

         {

          //  too much relocations? For Microsoft formats the number of relocs

          //  is written as the 1st relocation, see winnt.h, line 3931

          file_size += IMAGE_SIZEOF_RELOCATION;

         }

       }

      else

       {

        psecobj->Ish->PointerToRelocations = 0;

       }

     }

        //  Prepare for lineinfo

        if ((error = PE32_prepare_lineinfo_for_write(psecobj)) != MFL_OK) {

            return error;

        }

        if (psecobj->Ish->NumberOfLinenumbers > 0) {

            psecobj->Ish->PointerToLinenumbers = file_size;

            file_size += psecobj->Ish->NumberOfLinenumbers * IMAGE_SIZEOF_LINENUMBER;

        } else {

            psecobj->Ish->PointerToLinenumbers = 0;

        }

    }

    //  In the GNT architecture the section raw content should come in one piece.

    //  Set the pointer of the relocation table in the output file.

    if (mfl_od_omf(pfobj) == MFL_OMF_GNT32) {

        psecobj = MFL_OD_FIRST;

        while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj)) != MFL_OD_END) {

            if (psecobj->Ish->NumberOfRelocations > 0) {

                psecobj->Ish->PointerToRelocations = file_size;

                file_size += psecobj->Ish->NumberOfRelocations * IMAGE_SIZEOF_RELOCATION;

            } else {

                psecobj->Ish->PointerToRelocations = 0;

            }

        }

    }

    //  Update the Value field of all the define symbol in any section

    if ((error = PE32_update_coff_symbol(pfobj)) != MFL_OK) {

        return error;

    }

    pfobj->nthdr.FileHeader.PointerToSymbolTable = file_size;

    file_size += pfobj->nthdr.FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL;

    file_size += pfobj->str_size;

    return MFL_OK;

}

//-----------------------------------------------------------------------------

// -                      PE32_write_coff_file_header                           -

// -                                                                            -

// - Write the COFF file header.                                                -

// -----------------------------------------------------------------------------

static FUNC mfl_err PE32_write_coff_file_header (PE32_file_object *pfobj)

{

    mfl_err error;

#ifdef PECOFF32_EM

    if (mfl_od_omf(pfobj) == MFL_OMF_PE3264 ||

        (mfl_od_omf(pfobj) == MFL_OMF_COFF32 &&

         pfobj->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432 &&

         (pfobj->nthdr.FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)))

     {

      pfobj->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_32BIT_MACHINE;

      pfobj->nthdr.FileHeader.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;

      pfobj->nthdr.FileHeader.TimeDateStamp = time (NULL);

     }

    else

     {

      pfobj->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_32BIT_MACHINE;

      pfobj->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_LARGE_ADDRESS_AWARE;

      pfobj->nthdr.FileHeader.TimeDateStamp = time (NULL);

     }

     if (mfl_od_omf(pfobj) == MFL_OMF_COFF32)

     {

        pfobj->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_LARGE_ADDRESS_AWARE;

     }

#endif                                                                      //  PECOFF32_EM

    PE32_swap_filehdr(&pfobj->nthdr.FileHeader);

    //  Write the COFF file header

    if ((error = mfl_write(&pfobj->nthdr.FileHeader, IMAGE_SIZEOF_FILE_HEADER, (mfl_file_obj *)pfobj)) != MFL_OK) {

        return error;

    }

    //  Restore file header

    PE32_swap_filehdr(&pfobj->nthdr.FileHeader);

    return MFL_OK;

}

//-----------------------------------------------------------------------------

// -                      PE32_write_coff_sec_header                            -

// -                                                                            -

// - Write Coff section header table                                            -

// -----------------------------------------------------------------------------

static FUNC mfl_err PE32_write_coff_sec_header (PE32_file_object *pfobj)

{

    mfl_err             error;

    PE32_section_object *psecobj;

    psecobj = MFL_OD_FIRST;

    while ((psecobj = hash_get_next (pfobj->sec_ht, (mfl_hash_od)psecobj)) != MFL_OD_END) {

        if (IMAGE_SCN_CNT_CODE & psecobj->Ish->Characteristics) {

            psecobj->Ish->Characteristics &=

                ~(IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_CNT_UNINITIALIZED_DATA);

            psecobj->Ish->Characteristics |= (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ);

        } else if (IMAGE_SCN_CNT_INITIALIZED_DATA & psecobj->Ish->Characteristics) {

            psecobj->Ish->Characteristics &= ~IMAGE_SCN_CNT_UNINITIALIZED_DATA;

        } else if ((IMAGE_SCN_CNT_UNINITIALIZED_DATA & psecobj->Ish->Characteristics) == 0) {

            if (IMAGE_SCN_MEM_EXECUTE & psecobj->Ish->Characteristics) {

                psecobj->Ish->Characteristics |= IMAGE_SCN_CNT_CODE;

            } else if (IMAGE_SCN_MEM_READ & psecobj->Ish->Characteristics) {

                psecobj->Ish->Characteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;

            }

        }

#ifdef DUMMY_CODE

        //  Copied from PE32_set_sec_rt_attr()

        if (IMAGE_SCN_MEM_EXECUTE & psecobj->Ish->Characteristics) {

            psecobj->Ish->Characteristics &= ~IMAGE_SCN_CNT_INITIALIZED_DATA;

        } else if (IMAGE_SCN_MEM_READ & psecobj->Ish->Characteristics) {

            psecobj->Ish->Characteristics &= ~IMAGE_SCN_CNT_CODE;

        }

#endif                                                                      //  DUMMY_CODE

    if (psecobj->relocations_num > USHRT_MAX)

     {//  too much relocations

      psecobj->Ish->Characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL;

      psecobj->Ish->NumberOfRelocations = USHRT_MAX;

     }

        PE32_swap_shdr(psecobj->Ish);

        if ((error = mfl_write(psecobj->Ish, IMAGE_SIZEOF_SECTION_HEADER, (mfl_file_obj *)pfobj)) != MFL_OK) {

            return error;

        }

        //  Restore section header

        PE32_swap_shdr(psecobj->Ish);

    }

    return MFL_OK;

}

//-------------------------------------------------------------------------------

// -                     PE32_write_one_sec_content                               -

// -                                                                              -

// - Write Coff section's raw content and the section's relocation table.         -

// - Before the writing check if the calculation process is correct.              -

// ------------------------------------------------------------------------------

static FUNC mfl_err PE32_write_one_coff_sec_content (PE32_file_object *pfobj,

                                                PE32_section_object *psecobj)

{

 mfl_err            error;

 mfl_file_off       foff;

 mfl_rel_num        num_of_relocs;

 IMAGE_RELOCATION   first_reloc;

  //  Write the section raw content if for non .bss section

  if (PE32_is_sec_mem_expand(psecobj) == FALSE)

   {

    //  Check that the file calculation is correct

    if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK)

            return error;

    if (foff != psecobj->Ish->PointerToRawData)

            return MFL_ERR_INTERNAL;

    if ((error = mfl_write(psecobj->content, PE32_section_size(psecobj),

                            (mfl_file_obj *)pfobj)) != MFL_OK)

            return error;

   }

  //  In the GNT architecture the section raw content should come in one piece.

  if (mfl_od_omf(pfobj) != MFL_OMF_GNT32)

   {

    //  write the section relocation table if exist

    num_of_relocs = psecobj->relocations_num;

    if (num_of_relocs > 0)

     {

      //  Check that the file calculation is correct

      if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK)

                return error;

      if (foff != psecobj->Ish->PointerToRelocations)

                return MFL_ERR_INTERNAL;

      if (num_of_relocs > USHRT_MAX)

       {

        //  too much relocations? For Microsoft formats the number of relocs

        //  is written as the 1st relocation, see winnt.h, line 3931

        first_reloc.VirtualAddress = num_of_relocs;

        first_reloc.SymbolTableIndex = 0;

        first_reloc.Type = 0;

        if ((error = mfl_write(&first_reloc,

                               IMAGE_SIZEOF_RELOCATION,

                               (mfl_file_obj *)pfobj)) != MFL_OK)

                        return error;

       }

      if (IMAGE_SIZEOF_RELOCATION == sizeof(IMAGE_RELOCATION))

       {

        if ((error = mfl_write(psecobj->prblock,

                               (mfl_32size)num_of_relocs *

                                    IMAGE_SIZEOF_RELOCATION,

                               (mfl_file_obj *)pfobj)) != MFL_OK)

                    return error;

       }

      else

       {

        WORD i;

        for (i = 0; i < num_of_relocs; ++i)

         {

          if ((error = mfl_write(psecobj->prblock + i,

                                 IMAGE_SIZEOF_RELOCATION,

                                 (mfl_file_obj *)pfobj)) != MFL_OK)

                        return error;

         }

       }

     }

   }

  //  Write lineinfo if exist

  if (psecobj->Ish->NumberOfLinenumbers > 0)

   {

    //  Check that the file calculation is correct

    if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK)

            return error;

    if (foff != psecobj->Ish->PointerToLinenumbers)

            return MFL_ERR_INTERNAL;

    if ((error = mfl_write(psecobj->lineinfo,

                           (mfl_32size)psecobj->Ish->NumberOfLinenumbers *

                                IMAGE_SIZEOF_LINENUMBER,

                           (mfl_file_obj *)pfobj)) != MFL_OK)

            return error;

   }

    //  In the GNT architecture the section raw content should come in one piece.

    if (mfl_od_omf(pfobj) == MFL_OMF_GNT32) {

        psecobj = MFL_OD_FIRST;

        while ((psecobj = hash_get_next(pfobj->sec_ht, (mfl_hash_od)psecobj)) != MFL_OD_END) {

            //  write the section relocation table if exist

            if (psecobj->Ish->NumberOfRelocations > 0) {

                //  Check that the file calculation is correct

                if ((error = mfl_tell((mfl_file_obj *)pfobj,&foff)) != MFL_OK) {

                    return error;

                }

                if (foff != psecobj->Ish->PointerToRelocations) {

                    return MFL_ERR_INTERNAL;

                }

                if (IMAGE_SIZEOF_RELOCATION == sizeof(IMAGE_RELOCATION)) {

                    if ((error = mfl_write(psecobj->prblock,

                                           (mfl_32size)psecobj->Ish->NumberOfRelocations * IMAGE_SIZEOF_RELOCATION,

                                           (mfl_file_obj *)pfobj)) != MFL_OK) {

                        return error;

                    }

                } else {

                    WORD i;

                    for (i = 0; i < psecobj->Ish->NumberOfRelocations; ++i) {

                        if ((error = mfl_write(psecobj->prblock + i, IMAGE_SIZEOF_RELOCATION, (mfl_file_obj *)pfobj)) != MFL_OK) {

                            return error;

                        }

                    }

                }

            }

        }

    }

    return MFL_OK;

}

//--------------------------------------------------------------------------------

// -                     PE32_write_coff_sec_content                               -

// -                                                                               -

// - Write Coff sections' raw content and the sections' relocation table.          -

// - Before the writing check if the calculation process is correct.               -

// --------------------------------------------------------------------------------

static FUNC mfl_err PE32_write_coff_sec_content (PE32_file_object *pfobj)

{

    mfl_err             error;

    PE32_section_object *psecobj;

    mfl_file_off        foff;

    mfl_rel_num         num_of_relocs;

    IMAGE_RELOCATION    first_reloc;

    psecobj = MFL_OD_FIRST;

  while ((psecobj = hash_get_next(pfobj->sec_ht, (mfl_hash_od)psecobj)) != MFL_OD_END) {

        //  Write the section raw content if for non .bss section

        if (PE32_is_sec_mem_expand(psecobj) == FALSE) {

            //  Check that the file calculation is correct

            if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK) {

                return error;

            }

            if (foff != psecobj->Ish->PointerToRawData) {

                return MFL_ERR_INTERNAL;

            }

            if ((error = mfl_write(psecobj->content, PE32_section_size(psecobj), (mfl_file_obj *)pfobj)) != MFL_OK) {

                return error;

            }

        }

    //  In the GNT architecture the section raw content should come in one piece.

    if (mfl_od_omf(pfobj) != MFL_OMF_GNT32)

     {

      //  write the section relocation table if exist

      num_of_relocs = psecobj->relocations_num;

      if (num_of_relocs > 0)

       {

        //  Check that the file calculation is correct

        if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK)

                    return error;

        if (foff != psecobj->Ish->PointerToRelocations)

                    return MFL_ERR_INTERNAL;

       if (num_of_relocs > USHRT_MAX)

        {

         //  too much relocations? For Microsoft formats the number of relocs

         //  is written as the 1st relocation, see winnt.h, line 3931

         first_reloc.VirtualAddress = num_of_relocs;

         first_reloc.SymbolTableIndex = 0;

         first_reloc.Type = 0;

         if ((error = mfl_write(&first_reloc,

                                IMAGE_SIZEOF_RELOCATION,

                                (mfl_file_obj *)pfobj)) != MFL_OK)

                        return error;

        }

        if (IMAGE_SIZEOF_RELOCATION == sizeof(IMAGE_RELOCATION))

         {

          if ((error = mfl_write(psecobj->prblock,

                                 (mfl_32size)num_of_relocs *

                                    IMAGE_SIZEOF_RELOCATION,

                                 (mfl_file_obj *)pfobj)) != MFL_OK)

                        return error;

         }

        else

         {

          WORD i;

          for (i = 0; i < num_of_relocs; ++i)

           {

            if ((error = mfl_write(psecobj->prblock + i,

                                   IMAGE_SIZEOF_RELOCATION,

                                   (mfl_file_obj *)pfobj)) != MFL_OK)

                            return error;

           }

         }

       }

     }

        //  Write lineinfo if exist

        if (psecobj->Ish->NumberOfLinenumbers > 0) {

            //  Check that the file calculation is correct

            if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK) {

                return error;

            }

            if (foff != psecobj->Ish->PointerToLinenumbers) {

                return MFL_ERR_INTERNAL;

            }

            if ((error = mfl_write(psecobj->lineinfo,

                                   (mfl_32size)psecobj->Ish->NumberOfLinenumbers * IMAGE_SIZEOF_LINENUMBER,

                                   (mfl_file_obj *)pfobj)) != MFL_OK) {

                return error;

            }

        }

    }

    //  In the GNT architectura the section rawconten shuld come in one piece.

    if (mfl_od_omf(pfobj) == MFL_OMF_GNT32) {

        psecobj = MFL_OD_FIRST;

        while ((psecobj = hash_get_next(pfobj->sec_ht, (mfl_hash_od)psecobj)) != MFL_OD_END) {

            //  write the section relocation table if exist

            if (psecobj->Ish->NumberOfRelocations > 0) {

                //  Check that the file calculation is correct

                if ((error = mfl_tell((mfl_file_obj *)pfobj,&foff)) != MFL_OK) {

                    return error;

                }

                if (foff != psecobj->Ish->PointerToRelocations) {

                    return MFL_ERR_INTERNAL;

                }

                if (IMAGE_SIZEOF_RELOCATION == sizeof(IMAGE_RELOCATION)) {

                    if ((error = mfl_write(psecobj->prblock,

                                           (mfl_32size)psecobj->Ish->NumberOfRelocations * IMAGE_SIZEOF_RELOCATION,

                                           (mfl_file_obj *)pfobj)) != MFL_OK) {

                        return error;

                    }

                } else {

                    WORD i;

                    for (i = 0; i < psecobj->Ish->NumberOfRelocations; ++i) {

                        if ((error = mfl_write(psecobj->prblock + i, IMAGE_SIZEOF_RELOCATION, (mfl_file_obj *)pfobj)) != MFL_OK) {

                            return error;

                        }

                    }

                }

            }

        }

    }

    return MFL_OK;

}

//--------------------------------------------------------------------------------------

// -                           PE32_write_coff_symtab_strtab                             -

// -                                                                                     -

// - Write the Coff symbol table and the Coff string table after the symbol table.       -

// --------------------------------------------------------------------------------------

static FUNC mfl_err PE32_write_coff_symtab_strtab (PE32_file_object *pfobj)

{

    mfl_err      error;

    mfl_file_off foff;

    //  Check that the file calculation is correct

    if ((error = mfl_tell((mfl_file_obj *)pfobj, &foff)) != MFL_OK) {

        return error;

    }

    if ((unsigned)pfobj->nthdr.FileHeader.PointerToSymbolTable != foff) {

        return MFL_ERR_INTERNAL;

    }

    //  Write the Coff symbol table

    if (IMAGE_SIZEOF_SYMBOL == sizeof(IMAGE_SYMBOL)) {

        if ((error = mfl_write(pfobj->Coffsym,

                               pfobj->nthdr.FileHeader.NumberOfSymbols * IMAGE_SIZEOF_SYMBOL,

                               (mfl_file_obj *)pfobj)) != MFL_OK) {

            return error;

        }

    } else {

        DWORD i;

        for (i = 0; i < pfobj->nthdr.FileHeader.NumberOfSymbols; ++i) {

            if ((error = mfl_write(pfobj->Coffsym + i, IMAGE_SIZEOF_SYMBOL, (mfl_file_obj *)pfobj)) != MFL_OK) {

                return error;

            }

        }

    }

    //  Write the Coff string table

    *(UINT *)pfobj->strtab = mfl_endian_select_int(*(UINT *)pfobj->strtab, 0);

    if ((error = mfl_write(pfobj->strtab, pfobj->str_size, (mfl_file_obj *)pfobj)) != MFL_OK) {

        return error;

    }

    *(UINT *)pfobj->strtab = mfl_endian_select_int(*(UINT *)pfobj->strtab, 0);

    return MFL_OK;

}

#ifdef PECOFF32_EM

//---------------------------------------------------------------------------

// -                      PE32_64_write_pe_file_header                        -

// -                                                                          -

// - Write file headers                                                       -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_64_write_pe_file_header (PE32_file_object *fod)

{

    mfl_err error;

    if (fod->nthdr.OptionalHeader.pe3264.SectionAlignment < PE32_I386_PAGE_SIZE) {

        fod->nthdr.OptionalHeader.pe3264.SectionAlignment = PE32_I386_PAGE_SIZE;

    }

    if (fod->nthdr.OptionalHeader.pe3264.SectionAlignment >=

        ((fod->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE) ||

         (fod->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) ?

            PE32_EM_PAGE_SIZE : PE32_I386_PAGE_SIZE)

       ) {

        PE32_file_align(fod) = PE32_SECTOR_SIZE;

    } else {

        PE32_file_align(fod) = fod->nthdr.OptionalHeader.pe3264.SectionAlignment;

    }

    if ((error = mfl_write(&fod->doshdr, sizeof(fod->doshdr), (mfl_file_obj *)fod))

            != MFL_OK) {

        return error;

    }

    if ((error = PE32_write_file_pad_offset(fod, sizeof(fod->doshdr), (ULONG)fod->doshdr.e_lfanew)) != MFL_OK) {

        return error;

    }

    fod->nthdr.Signature = IMAGE_NT_SIGNATURE;

    fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;

    fod->nthdr.FileHeader.Characteristics &= ~IMAGE_FILE_32BIT_MACHINE;

    fod->nthdr.FileHeader.NumberOfSections = (USHORT)PE32_file_get_sec_num(fod);

    fod->nthdr.FileHeader.TimeDateStamp = time (NULL);

    fod->nthdr.FileHeader.SizeOfOptionalHeader = IMAGE_SIZEOF_NT_OPTIONAL_HEADER_PE3264;

    fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_BYTES_REVERSED_LO |

        IMAGE_FILE_LOCAL_SYMS_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED;

    //  set the pe header virsions

    fod->nthdr.OptionalHeader.pe3264.Magic = PE3264_NT_HEADER_MAGIC;

    fod->nthdr.OptionalHeader.pe3264.MajorLinkerVersion = VER_MAJOR;

    fod->nthdr.OptionalHeader.pe3264.MinorLinkerVersion = VER_MINOR;

    fod->nthdr.OptionalHeader.pe3264.MajorOperatingSystemVersion = PE32_MAJOR_OS_VERSION;

    fod->nthdr.OptionalHeader.pe3264.MinorOperatingSystemVersion = PE32_MINOR_OS_VERSION;

    fod->nthdr.OptionalHeader.pe3264.MajorImageVersion = PE32_MAJOR_IMAGE_VERSION;

    fod->nthdr.OptionalHeader.pe3264.MinorImageVersion = PE32_MINOR_IMAGE_VERSION;

    fod->nthdr.OptionalHeader.pe3264.MajorSubsystemVersion = PE32_MAJOR_SUBSYS_VERSION;

    fod->nthdr.OptionalHeader.pe3264.MinorSubsystemVersion = PE32_MINOR_SUBSYS_VERSION;

                                        //  calculate file header size

                                        //  header size + section header table size

    fod->nthdr.OptionalHeader.pe3264.SizeOfHeaders = (fod->doshdr.e_lfanew + sizeof(fod->nthdr.Signature) +

                sizeof (IMAGE_FILE_HEADER) + IMAGE_SIZEOF_NT_OPTIONAL_HEADER_PE3264 +

                sizeof (IMAGE_SECTION_HEADER) * PE32_file_sec_num (fod)

                //  aligned to file alignment

                + PE32_file_align (fod) -1) & ~(PE32_file_align (fod) -1);

    PE32_file_get_grouped_size(fod);

    //  calculate the image size

    if ((error = PE32_calculate_image_size(fod)) != MFL_OK) {

        return error;

    }

    //  set in the file header table the address and the size of the PE spacial

    //  section like .rsrc , .debug                                             

    if ((error = PE32_set_ft_spacial_sec(fod)) != MFL_OK) {

        return error;

    }

    fod->nthdr.OptionalHeader.pe3264.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;

#ifdef BIG_ENDIAN

    //  patch the fields

    {IMAGE_NT_HEADERS_PE3264 nt_header;

     nt_header = fod->nthdr;

     mfl_int_swap((int *)&nt_header.Signature);

     PE32_swap_filehdr(&nt_header.FileHeader);

     PE32_swap_pehdr(NULL, &nt_header);

     error = mfl_write(&nt_header, sizeof(nt_header), (mfl_file_obj *)fod);

     //  swap the headers back

     mfl_int_swap((int *)&nt_header.Signature);

     PE32_swap_filehdr(&nt_header.FileHeader);

     PE32_swap_pehdr(NULL, &nt_header);

    }

#else

    error = mfl_write(&fod->nthdr, sizeof(fod->nthdr), (mfl_file_obj *)fod);

#endif

    if (error == MFL_OK) {

        error = PE32_write_file_pad_offset (fod, fod->doshdr.e_lfanew +

                                            sizeof(fod->nthdr),

                                            fod->doshdr.e_lfanew +

                                            sizeof(fod->nthdr.Signature) +

                                            sizeof(IMAGE_FILE_HEADER) +

                                            IMAGE_SIZEOF_NT_OPTIONAL_HEADER_PE3264);

    }

    return error;

}

#endif                                                                      //  PECOFF32_EM

//---------------------------------------------------------------------------

// -                      PE32_write_pe_file_header                           -

// -                                                                          -

// - Write file headers                                                       -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_pe_file_header (PE32_file_object *fod)

{

    mfl_err error;

#ifdef PECOFF32_EM

    if (mfl_od_omf(fod) == MFL_OMF_PE3264)

        return PE32_64_write_pe_file_header(fod);

#endif                                                                      //  PECOFF32_EM

    if (fod->nthdr.OptionalHeader.pe32.SectionAlignment < PE32_SECTOR_SIZE) {

        fod->nthdr.OptionalHeader.pe32.SectionAlignment = PE32_SECTOR_SIZE;

    }

    if (fod->nthdr.OptionalHeader.pe32.SectionAlignment >=

#ifdef PECOFF32_EM

        ((fod->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_TAHOE ||

          fod->nthdr.FileHeader.Machine == IMAGE_FILE_MACHINE_IA6432) ?

        PE32_EM_PAGE_SIZE : PE32_I386_PAGE_SIZE)

#else                                                                       //  PECOFF32_EM

        PE32_I386_PAGE_SIZE

#endif                                                                      //  PECOFF32_EM

       ) {

        PE32_file_align(fod) = PE32_SECTOR_SIZE;

    } else {

        PE32_file_align(fod) = fod->nthdr.OptionalHeader.pe32.SectionAlignment;

    }

    if ((error = mfl_write(&fod->doshdr, sizeof(fod->doshdr), (mfl_file_obj *)fod)) != MFL_OK) {

        return error;

    }

    if ((error = PE32_write_file_pad_offset(fod, sizeof(fod->doshdr), (ULONG)fod->doshdr.e_lfanew)) != MFL_OK) {

        return error;

    }

#ifdef PECOFF32_EM

    fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_32BIT_MACHINE;

    fod->nthdr.FileHeader.Characteristics &= ~(WORD)IMAGE_FILE_LARGE_ADDRESS_AWARE;

#else                                                                       //  PECOFF32_EM

//   fod->nthdr.FileHeader.Machine = IMAGE_FILE_MACHINE_I386;

    fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_32BIT_MACHINE;

#endif                                                                      //  PECOFF32_EM

    fod->nthdr.FileHeader.NumberOfSections = (USHORT)PE32_file_get_sec_num(fod);

    fod->nthdr.FileHeader.TimeDateStamp = time (NULL);

    fod->nthdr.FileHeader.SizeOfOptionalHeader = IMAGE_SIZEOF_NT_OPTIONAL_HEADER;

    fod->nthdr.FileHeader.Characteristics |= IMAGE_FILE_BYTES_REVERSED_LO |

        IMAGE_FILE_LOCAL_SYMS_STRIPPED | IMAGE_FILE_LINE_NUMS_STRIPPED;

    //  set the pe header virsions

    fod->nthdr.OptionalHeader.pe32.Magic = PE32_NT_HEADER_MAGIC;

    fod->nthdr.OptionalHeader.pe32.MajorLinkerVersion = VER_MAJOR;

    fod->nthdr.OptionalHeader.pe32.MinorLinkerVersion = VER_MINOR;

    fod->nthdr.OptionalHeader.pe32.MajorOperatingSystemVersion = PE32_MAJOR_OS_VERSION;

    fod->nthdr.OptionalHeader.pe32.MinorOperatingSystemVersion = PE32_MINOR_OS_VERSION;

    fod->nthdr.OptionalHeader.pe32.MajorImageVersion = PE32_MAJOR_IMAGE_VERSION;

    fod->nthdr.OptionalHeader.pe32.MinorImageVersion = PE32_MINOR_IMAGE_VERSION;

    fod->nthdr.OptionalHeader.pe32.MajorSubsystemVersion = PE32_MAJOR_SUBSYS_VERSION;

    fod->nthdr.OptionalHeader.pe32.MinorSubsystemVersion = PE32_MINOR_SUBSYS_VERSION;

                                        //  calculate file header size

                                        //  header size + section header table size

    fod->nthdr.OptionalHeader.pe32.SizeOfHeaders = (fod->doshdr.e_lfanew + sizeof(fod->nthdr.Signature) +

                sizeof (IMAGE_FILE_HEADER) + IMAGE_SIZEOF_NT_OPTIONAL_HEADER +

                sizeof (IMAGE_SECTION_HEADER) * PE32_file_sec_num (fod)

                //  aligned to file alignment

                + PE32_file_align (fod) -1) & ~(PE32_file_align (fod) -1);

    PE32_file_get_grouped_size(fod);

    //  calculate the image size

    if ((error = PE32_calculate_image_size(fod)) != MFL_OK) {

        return error;

    }

    //  set in the file header table the address and the size of the PE spacial

    //  section like .rsrc , .debug                                             

    if ((error = PE32_set_ft_spacial_sec(fod)) != MFL_OK) {

        return error;

    }

    fod->nthdr.OptionalHeader.pe32.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;

    //  write only the PE32 header

#ifdef BIG_ENDIAN

    //  patch the fields

    {IMAGE_NT_HEADERS_PE3264 nt_header;

     nt_header = fod->nthdr;

     mfl_int_swap((int *)&nt_header.Signature);

     PE32_swap_filehdr(&nt_header.FileHeader);

     PE32_swap_pehdr(NULL, &nt_header);

     error = mfl_write(&nt_header, sizeof(nt_header.Signature) +

                                    sizeof(IMAGE_FILE_HEADER),

                        (mfl_file_obj *)fod);

     if (error == MFL_OK)

        error = mfl_write(&nt_header.OptionalHeader.pe32,

                            sizeof(nt_header.OptionalHeader.pe32),

                            (mfl_file_obj *)fod);

     //  swap the headers back

     mfl_int_swap((int *)&nt_header.Signature);

     PE32_swap_filehdr(&nt_header.FileHeader);

     PE32_swap_pehdr(NULL, &nt_header);

    }

#else

    error = mfl_write(&fod->nthdr, sizeof(fod->nthdr.Signature) +

                                    sizeof(IMAGE_FILE_HEADER),

                        (mfl_file_obj *)fod);

    if (error == MFL_OK)

        error = mfl_write(&fod->nthdr.OptionalHeader.pe32,

                            sizeof(fod->nthdr.OptionalHeader.pe32),

                            (mfl_file_obj *)fod);

#endif

    if (error == MFL_OK) {

        error = PE32_write_file_pad_offset (fod, fod->doshdr.e_lfanew +

                                            sizeof(fod->nthdr.Signature) +

                                            sizeof(IMAGE_FILE_HEADER) +

                                            IMAGE_SIZEOF_NT_OPTIONAL_HEADER,

                                            fod->doshdr.e_lfanew +

                                            sizeof(fod->nthdr.Signature) +

                                            sizeof(IMAGE_FILE_HEADER) +

                                            IMAGE_SIZEOF_NT_OPTIONAL_HEADER);

    }

    return error;

}

// -------------------------------------------------------------------------

//                        PE32_calculate_image_size                         

//                                                                          

//  Calculate the size of the image file that load to the memory in the run

//  time                                                                    

// -------------------------------------------------------------------------

static FUNC mfl_err PE32_calculate_image_size (PE32_file_object *pfobj)

{

    PE32_secgrp_object *psecgobj;

    PE32_size          image_size = 0;

    PE32_size          sg_image;

    int                idx;

    //  In the meantime we assume the file doesn't have base relocations

    //  and therefore cannot be relocated at run time

    pfobj->nthdr.FileHeader.Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;

    for (psecgobj = pfobj->secgrps;

         psecgobj != MFL_OD_NULL && psecgobj != MFL_OD_END;

         psecgobj = (PE32_secgrp_object *)psecgobj->next) {

        //  calculate regular section size

        if (psecgobj->sec != MFL_OD_NULL) {

            sg_image = (PE32_section_size(psecgobj->sec) + PE32_section_vaddr(psecgobj->sec) +

                PE32_get_object_align(pfobj) - 1) & ~(PE32_get_object_align(pfobj) - 1);

            image_size = MAX(image_size, sg_image);

            continue;

        }

        //  calculate import section size

        if ((psecgobj->internal & PE32_SECTION_EXPAND) &&

            ((psecgobj->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_IMPORT)) {

            idx = image_directory_idx[PE32_INTERNAL_SEC_IMPORT];

            sg_image = (PE32_file_dir_vaddr(pfobj, idx) + PE32_file_dir_size(pfobj, idx) +

                PE32_get_object_align(pfobj) - 1) & ~(PE32_get_object_align(pfobj) - 1);

            image_size = MAX(image_size, sg_image);

            continue;

        }

        //  calculate export section size

        if ((psecgobj->internal & PE32_SECTION_EXPAND) &&

            ((psecgobj->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_EXPORT)) {

            idx = image_directory_idx[PE32_INTERNAL_SEC_EXPORT];

            sg_image = (PE32_file_dir_vaddr(pfobj, idx) + PE32_file_dir_size(pfobj, idx) +

                PE32_get_object_align(pfobj) - 1) & ~(PE32_get_object_align(pfobj) - 1);

            image_size = MAX(image_size, sg_image);

            continue;

        }

        // calculate relocation size

        if ((psecgobj->internal & PE32_SECTION_EXPAND) &&

            ((psecgobj->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_RELOC)) {

            idx = image_directory_idx[PE32_INTERNAL_SEC_RELOC];

            sg_image = (PE32_file_dir_vaddr(pfobj, idx) + PE32_file_dir_size(pfobj, idx) +

                PE32_get_object_align(pfobj) - 1) & ~(PE32_get_object_align(pfobj) - 1);

            image_size = MAX(image_size, sg_image);

            //  The file does have base relocations

            pfobj->nthdr.FileHeader.Characteristics &= ~(ULONG)IMAGE_FILE_RELOCS_STRIPPED;

            continue;

        }

    }

    IMAGE_NT_HEADERS_OptionalHeader(pfobj->nthdr, SizeOfImage) = image_size;

    return MFL_OK;

}

static FUNC int cmpv (const void *v1, const void *v2)

{

    return ((struct sg_vlist *)v1)->vaddr - ((struct sg_vlist *)v2)->vaddr;

}

//---------------------------------------------------------------------------

// -                       PE32_write_pe_sections                             -

// -                                                                          -

// - Write section function                                                   -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_pe_sections (PE32_file_object *fod)

{

    mfl_err error = MFL_OK;

    struct sg_vlist *sgl;

    PE32_secgrp_object *sg;

    int i;

    if ((sgl = mfl_malloc(fod->secgrp_num * sizeof(struct sg_vlist))) == NULL) {

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    }

    for (i=0, sg=fod->secgrps; sg != NULL; i++, sg = (PE32_secgrp_object *)sg->next) {

        sgl[i].sg = sg;

        if (sg->sec != NULL) {

            sgl[i].vaddr = PE32_section_vaddr(sg->sec);

        } else if (sg->internal & PE32_SECTION_EXPAND) {

            sgl[i].vaddr = PE32_file_dir_vaddr(fod,

                image_directory_idx[sg->internal & PE32_INTERNAL_OVRHD_MASK]);

        } else {

            sgl[i].vaddr = 0;

        }

    }

    qsort(sgl, (unsigned)fod->secgrp_num, sizeof(struct sg_vlist), cmpv);

    error = PE32_write_pe_section_header(fod, sgl);

    if (error == MFL_OK) {

        error = PE32_write_pe_section_content(fod, sgl);

    }

    mfl_free(sgl);

    return error;

}

//---------------------------------------------------------------------------

// -                    PE32_write_pe_section_header                          -

// -                                                                          -

// - Write header for all sections including internal secions.                -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_pe_section_header

    (PE32_file_object *fod, struct sg_vlist *sgl)

{

    PE32_size size;

    PE32_offset file_ptr;

    int i, j;

    mfl_err error = MFL_OK;

#if 0

    //  verify that overhead on relocations counted

    if ((fod->ovrhd & PE32_INTERNAL_OVRHD_MASK) == 0)

        return MFL_ERR_OVERHD_MIS;

#endif

    //  calculate first section file offset

    //  header size + section header table size

    file_ptr = (fod->doshdr.e_lfanew + sizeof(fod->nthdr.Signature) +

                sizeof(IMAGE_FILE_HEADER) + IMAGE_SIZEOF_NT_OPTIONAL_HEADER +

                sizeof(IMAGE_SECTION_HEADER) *  PE32_file_sec_num(fod) +

                //  aligned to file alignment

                + PE32_file_align(fod) - 1) & ~(PE32_file_align(fod) - 1);

    for (i = j = 0; i < fod->secgrp_num; i++) {

        //  write regular section header entry

        if (sgl[i].sg->sec != MFL_OD_NULL) {

            //  VirtualSize will contain actual section size

            sgl[i].sg->sec->Ish->Misc.VirtualSize = size = PE32_section_size(sgl[i].sg->sec);

            if (PE32_is_sec_mem_expand(sgl[i].sg->sec) == FALSE) {

                sgl[i].sg->sec->Ish->PointerToRawData = file_ptr;

                PE32_section_size(sgl[i].sg->sec) =

                    (size + PE32_file_align(fod) - 1) & ~(PE32_file_align(fod) - 1);

                file_ptr += PE32_section_size(sgl[i].sg->sec);

            } else {

                //  set zero to the pointer to the raw content

                //  if it is bss section                      

                sgl[i].sg->sec->Ish->PointerToRawData = 0;

                PE32_section_size(sgl[i].sg->sec) = 0;

            }

            if ((error = mfl_write (sgl[i].sg->sec->Ish, sizeof(IMAGE_SECTION_HEADER),

                 (mfl_file_obj *)fod)) != MFL_OK)

            {

                break;

            }

            PE32_section_size(sgl[i].sg->sec) = size;

            continue;

        }

        //  write import section header entry

        if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&

            ((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_IMPORT)) {

            if ((error = PE32_write_internal_hdr(fod, PE32_INTERNAL_SEC_IMPORT,

                         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ,

                         &file_ptr)) != MFL_OK)

            {

                return error;

            }

            continue;

        }

        //  write export section header entry

        if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&

            ((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_EXPORT)) {

            if ((error = PE32_write_internal_hdr(fod, PE32_INTERNAL_SEC_EXPORT,

                         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ,

                         &file_ptr)) != MFL_OK) {

                return error;

            }

            continue;

        }

        //  relocation section header

        if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&

            ((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_RELOC)) {

            if ((error = PE32_write_internal_hdr(fod, PE32_INTERNAL_SEC_RELOC,

                         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_READ,

                         &file_ptr)) != MFL_OK) {

                return error;

            }

            continue;

        }

    }

    //  Write gep of zero show the contenue of the file will be align in

    //  the file alignment                                               

    //  calculate first section file offset

    //  header size + section header table size

    file_ptr = fod->doshdr.e_lfanew + sizeof(fod->nthdr.Signature) +

               sizeof (IMAGE_FILE_HEADER) + IMAGE_SIZEOF_NT_OPTIONAL_HEADER +

               sizeof (IMAGE_SECTION_HEADER) *  PE32_file_sec_num (fod);

    if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {

        return error;

    }

    return error;

}

//---------------------------------------------------------------------------

// -                     PE32_write_internal_hdr                              -

// -                                                                          -

// - Fill and write internal section header                                   -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_internal_hdr (PE32_file_object *fod,

                                             int internal, ULONG charac,

                                             PE32_offset *file_ptr)

{

    IMAGE_SECTION_HEADER sech;

    mfl_err error;

    int idx;

    memset(&sech, 0, sizeof(IMAGE_SECTION_HEADER));

    strcpy((mfl_str)sech.Name, str_internal[internal]);

    idx = image_directory_idx[internal];

    sech.VirtualAddress = PE32_file_dir_vaddr(fod, idx);

    sech.Misc.VirtualSize = PE32_file_dir_size(fod, idx);

    sech.SizeOfRawData = (PE32_file_dir_size(fod, idx) + PE32_file_align(fod) - 1) &

        ~(PE32_file_align(fod) - 1);

    sech.PointerToRawData = *file_ptr;

    sech.Characteristics = charac;

    error = mfl_write(&sech, sizeof(IMAGE_SECTION_HEADER), (mfl_file_obj *)fod);

    *file_ptr += sech.SizeOfRawData;

    return error;

}

//---------------------------------------------------------------------------

// -                    PE32_write_pe_section_content                         -

// -                                                                          -

// - Write in file content of all sections                                    -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_pe_section_content

    (PE32_file_object *fod, struct sg_vlist *sgl)

{

    int i;

    PE32_offset file_ptr, Check_off;

    mfl_err error;

    //  calculate file offset

    file_ptr = IMAGE_NT_HEADERS_OptionalHeader(fod->nthdr, SizeOfHeaders);

    if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {

        return error;

    }

    for (i = 0; i < fod->secgrp_num; i++) {

        Check_off = ftell(fod->mflfh.fhandle);

        if (sgl[i].sg->sec != NULL && PE32_is_sec_mem_expand(sgl[i].sg->sec) == FALSE) {

            if ((error = mfl_write(sgl[i].sg->sec->content,

                                   sgl[i].sg->sec->Ish->SizeOfRawData,

                                   (mfl_file_obj *)fod)) != MFL_OK) {

                break;

            }

            file_ptr += sgl[i].sg->sec->Ish->SizeOfRawData;

            if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {

                return error;

            }

            continue;

        }

        if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&

            ((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_IMPORT)) {

            if ((error = PE32_write_import_symbols(fod)) != MFL_OK) {

                return error;

            }

            file_ptr += PE32_file_dir_size(fod, IMAGE_DIRECTORY_ENTRY_IMPORT);

            if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {

                return error;

            }

            continue;

        }

        if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&

            ((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_EXPORT)) {

            if ((error = PE32_write_export_symbols(fod)) != MFL_OK) {

                return error;

            }

            file_ptr += PE32_file_dir_size(fod, IMAGE_DIRECTORY_ENTRY_EXPORT);

            if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {

                return error;

            }

            continue;

        }

        if ((sgl[i].sg->internal & PE32_SECTION_EXPAND) &&

            ((sgl[i].sg->internal & PE32_INTERNAL_OVRHD_MASK) == PE32_INTERNAL_SEC_RELOC)) {

            if ((error = PE32_write_basereloc(fod, sgl)) != MFL_OK) {

                return error;

            }

            file_ptr += PE32_file_dir_size(fod, IMAGE_DIRECTORY_ENTRY_BASERELOC);

            if ((error = PE32_write_file_pad_align(fod, &file_ptr, PE32_file_align(fod))) != MFL_OK) {

                return error;

            }

            continue;

        }

    }

    return error;

}

//---------------------------------------------------------------------------

// -                       PE32_write_basereloc                               -

// -                                                                          -

// - Write executable relocataions                                            -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_basereloc (PE32_file_object *fod,

                                          struct sg_vlist *sgl)

{

    mfl_err error;

    int i, j, nblock;

    void *relbuf;

    IMAGE_BASE_RELOCATION *block_header;

    USHORT *type_offset;

    PE32_vaddr addr;

    PE32_reloc_object *rod;

    PE32_section_object *sec;

    mfl_file_off foff;

    mfl_tell((mfl_file_obj *)fod,&foff);

    if ((relbuf = block_header =

         mfl_malloc (PE32_file_dir_size (fod,IMAGE_DIRECTORY_ENTRY_BASERELOC)+

                     sizeof (USHORT))) == NULL)

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    //  for each section

    for (i=0; i < fod->secgrp_num; i++)

        if (sgl[i].sg->sec != NULL) {

            sec = sgl[i].sg->sec;

            //  get number of 4K blocks

            nblock = (PE32_section_size (sec) + 0xfff) >> 12;

            //  for each 4K block

            for (j=0, addr = PE32_section_vaddr(sec); j < nblock;

                 j++, addr += 0x1000) {

                //  if block has relocations

                if (sec->pdir[j].rcnt != 0) {

                    //  fill block header

                    block_header->VirtualAddress = addr;

                    block_header->SizeOfBlock = sizeof (IMAGE_BASE_RELOCATION) +

                        sizeof (USHORT) * sec->pdir[j].rcnt;

                    //  for each relocation in block

                    type_offset = (USHORT *)(block_header + 1);

                    for (rod=(PE32_reloc_object *)sec->pdir[j].rod;

                         rod != NULL; rod = rod->next, type_offset++)

                        //  fill type-offset value

                        *type_offset = (rod->offset & 0xfff)| (rod->type << 12);

                    //  pad next entry (maybe last one)

                    *type_offset = 0;

                    //  advance to next block header

                    block_header = (IMAGE_BASE_RELOCATION *)((char *)block_header + block_header->SizeOfBlock);

                }

            }

        }

    //  write relocations

    error = mfl_write (relbuf,

                       PE32_file_dir_size(fod,IMAGE_DIRECTORY_ENTRY_BASERELOC),

                       (mfl_file_obj *)fod);

    mfl_tell((mfl_file_obj *)fod,&foff);

    mfl_free (relbuf);

    return error;

}

//---------------------------------------------------------------------------

// -                    PE32_write_export_symbols                             -

// -                                                                          -

// - Write export symbol table                                                -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_export_symbols (PE32_file_object *fod)

{

    mfl_err error;

    int i;

    void *symbuf;

    IMAGE_EXPORT_DIRECTORY *st_header;

    PE32_symtab_object *stod;

    static mfl_sym_grp grp = MFL_SYM_EXPORT;

    static mfl_next next = {MFL_OD_FIRST, MFL_OBJ_SYMTAB, MFL_PROP_SYMTAB_GRP,

                                &grp};

    PE32_symbol_object *sym;

    PE32_size sec_size;

    PE32_vaddr sec_addr;

    PE32_vaddr *func_addr;

    PE32_vaddr *name_addr;

    USHORT *ord;

    char *func_name;

    PE32_vaddr name_ptr;

    int sym_num;

    int len;

    mfl_file_off foff;

    mfl_tell((mfl_file_obj *)fod,&foff);

    sec_size = PE32_file_dir_size (fod,IMAGE_DIRECTORY_ENTRY_EXPORT);

    sec_addr = PE32_file_dir_vaddr (fod,IMAGE_DIRECTORY_ENTRY_EXPORT);

    if ((symbuf = st_header = mfl_malloc (sec_size)) == NULL)

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    //  get numbet of symbols in all export symbol tables

    next.od = MFL_OD_FIRST;

    sym_num = 0;

    while ((error = PE32_get_next_symtab (fod, &next, &stod)) == MFL_OK) {

        sym_num += stod->syms->item_num;

        next.od = (mfl_od)stod;

    }

    //  fill symbol table header

    st_header->Characteristics = 0;

    st_header->TimeDateStamp = time(NULL);

    st_header->MajorVersion = 0;

    st_header->MinorVersion = 0;

    st_header->Base = 1;

    st_header->NumberOfFunctions = sym_num;

    st_header->NumberOfNames = sym_num;

    st_header->AddressOfFunctions = sec_addr +  sizeof (IMAGE_EXPORT_DIRECTORY);

    st_header->AddressOfNames = st_header->AddressOfFunctions + sym_num;

    st_header->AddressOfNameOrdinals = st_header->AddressOfNames + sym_num;

    st_header->Name = (ULONG)(st_header->AddressOfNameOrdinals + sym_num);

    //  calculate pointer to smaller tables

    func_addr = (PE32_vaddr *)(st_header + 1);

    name_addr = func_addr + sym_num;

    ord = (PUSHORT)(name_addr + sym_num);

    func_name = (char *)(ord + sym_num);

    name_ptr = st_header->Name;

    strcpy (func_name, fod->mflfh.name);

    len = strlen (func_name) + 1;

    func_name += len;

    name_ptr += len;

    i = 0;

    //  for all export symbol tables

    next.od = MFL_OD_FIRST;

    while ((error = PE32_get_next_symtab (fod, &next, &stod)) == MFL_OK) {

        next.od = (mfl_od)stod;

        //  for all symbols in symbol table

        sym = MFL_OD_FIRST;

        while ((sym = hash_get_next (stod->syms, (mfl_hash_od)sym))

                != MFL_OD_END) {

            func_addr[i] = PE32_symbol_vaddr (sym);

            name_addr[i] = name_ptr;

            ord[i] = i;

            strcpy (func_name, PE32_symbol_name(sym));

            len = strlen (func_name) + 1;

            func_name += len;

            name_ptr += len;

            i++;

        }

    }

    //  reset the rest of the buffer

    memset (func_name, 0, sec_size - ((ULONG)func_name - (ULONG)st_header));

    //  write symbols

    error = mfl_write (st_header, sec_size, (mfl_file_obj *)fod);

    mfl_tell((mfl_file_obj *)fod,&foff);

    mfl_free (st_header);

    return error;

}

//---------------------------------------------------------------------------

// -                    PE32_write_import_symbols                             -

// -                                                                          -

// - Write import symbol table                                                -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_import_symbols (PE32_file_object *fod)

{

    mfl_err error;

    PE32_size sec_size;

    PE32_vaddr sec_addr;

    unsigned int i;

    int j,len;

    void *symbuf;

    int sym_num;

    int st_num;

    PE32_symtab_object *stod;

    PE32_symbol_object *sym;

    PE32_vaddr *adr_tab_1, *adr_tab_2;

    PE32_vaddr *ptr_tab_1, *ptr_tab_2;

    IMAGE_IMPORT_BY_NAME *adr_hint_tab;

    IMAGE_IMPORT_BY_NAME *ptr_hint_tab;

    IMAGE_IMPORT_DESCRIPTOR *st_header;

    static mfl_sym_grp grp = MFL_SYM_IMPORT;

    static mfl_next next = {MFL_OD_FIRST, MFL_OBJ_SYMTAB, MFL_PROP_SYMTAB_GRP,

                                &grp};

    mfl_file_off foff;

    mfl_tell((mfl_file_obj *)fod,&foff);

    sec_size = PE32_file_dir_size (fod,IMAGE_DIRECTORY_ENTRY_IMPORT);

    sec_addr = PE32_file_dir_vaddr (fod,IMAGE_DIRECTORY_ENTRY_IMPORT);

    if ((symbuf = st_header = mfl_malloc (sec_size)) == NULL)

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    //  for all import symbol tables

    next.od = MFL_OD_FIRST;

    sym_num = 0;

    st_num = 0;

    while ((error = PE32_get_next_symtab (fod, &next, &stod)) == MFL_OK) {

        sym_num += stod->syms->item_num;

        st_num++;

        next.od = (mfl_od)stod;

    }

    //  image based addresses

    adr_tab_1 = (PE32_vaddr *)(sec_addr + sizeof(IMAGE_IMPORT_DESCRIPTOR) * (st_num+1));

    adr_tab_2 = adr_tab_1 + sym_num + st_num;

    adr_hint_tab = (IMAGE_IMPORT_BY_NAME *)(adr_tab_2 + sym_num + st_num);

    //  buffer addresses

    ptr_tab_1 = (PE32_vaddr *)(st_header + st_num + 1);

    ptr_tab_2 = ptr_tab_1 + sym_num + st_num;

    ptr_hint_tab =  (IMAGE_IMPORT_BY_NAME *)(ptr_tab_2 + sym_num + st_num);

    next.od = MFL_OD_FIRST;

    for (j=0; j < st_num; j++) {

        //  get next symbol table

        if ((error = PE32_get_next_symtab (fod, &next, &stod)) != MFL_OK)

            return error;

        next.od = (mfl_od)stod;

        //  fill symbol table header entry

        st_header[j].Characteristics = (ULONG)adr_tab_1;

        st_header[j].TimeDateStamp = 0;

        st_header[j].ForwarderChain = 0;

        st_header[j].Name = (ULONG)adr_hint_tab;

        // st_header[j].FirstThunk = (IMAGE_THUNK_DATA -)adr_tab_2;

        st_header[j].FirstThunk = (DWORD)adr_tab_2;

        //  copy shared file name

        strcpy ((char *)ptr_hint_tab, stod->file);

        ((char *)ptr_hint_tab) [-1] = '\0';

        //  advance pointers

        ptr_hint_tab =

          (IMAGE_IMPORT_BY_NAME *)(ptr_hint_tab + ((strlen (stod->file) + 2) & (unsigned)~1));

        adr_hint_tab =

          (IMAGE_IMPORT_BY_NAME *)((char *)adr_hint_tab +

                                   ((strlen (stod->file) + 2) & (unsigned)~1));

        sym = MFL_OD_FIRST;

        for (i=0; i < stod->syms->item_num; i++) {

            sym = hash_get_next (stod->syms, (mfl_hash_od)sym);

            //  fill lookup and address table

            ptr_tab_1[i] = (PE32_vaddr)adr_hint_tab;

            ptr_tab_2[i] = (PE32_vaddr)adr_hint_tab;

            //  fill hint-name table

            ptr_hint_tab->Hint = (USHORT)sym->ord;

            strcpy ((mfl_str)ptr_hint_tab->Name, sym->name);

            ((char *)ptr_hint_tab) [-1] = '\0';

            //  addvance pointers

            len =  (sizeof (USHORT) + strlen (sym->name) + 2) & (unsigned)~1;

            adr_hint_tab = (IMAGE_IMPORT_BY_NAME *)((char *)adr_hint_tab + len);

            ptr_hint_tab = (IMAGE_IMPORT_BY_NAME *)((char *)ptr_hint_tab + len);

        }

        //  advance image base addresses

        adr_tab_1 += stod->syms->item_num + 1;

        adr_tab_2 += stod->syms->item_num + 1;

        //  advance table pointers

        ptr_tab_1[stod->syms->item_num] = 0;

        ptr_tab_2[stod->syms->item_num] = 0;

        ptr_tab_1 += stod->syms->item_num + 1;

        ptr_tab_2 += stod->syms->item_num + 1;

    }

     if (st_num > 0)

        memset(&st_header[st_num],0,sizeof(IMAGE_IMPORT_DESCRIPTOR));

    //  write import table

    if ((error = mfl_write (symbuf,sec_size,(mfl_file_obj *)fod)) != MFL_OK)

       return error;

    mfl_tell((mfl_file_obj *)fod,&foff);

    mfl_free (symbuf);

    return MFL_OK;

}

//---------------------------------------------------------------------------

// -                        PE32_write_file_pad_align                         -

// -                                                                          -

// - Pad file to required alignment                                           -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_file_pad_align (PE32_file_object *fod,

                                               PE32_offset *file_ptr,

                                               PE32_align align)

{

    PE32_offset end;

    char *buf;

    PE32_size size;

    mfl_err error;

    mfl_file_off foff;

    mfl_tell((mfl_file_obj *)fod,&foff);

    //  calculate next aligned offset

    end = (*file_ptr + align - 1) & ~(align-1);

    //  return if offset already aligned

    if (end == *file_ptr)

        return MFL_OK;

    //  calculate fill size

    size = end - *file_ptr;

    *file_ptr = end;

    //  allocate and reset pad buffer

    if ((buf = mfl_malloc (size)) == NULL)

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    memset (buf, 0, size);

    //  write the pad buffer

    error = mfl_write (buf, size, (mfl_file_obj *)fod);

    //  free pad buffer

    mfl_tell((mfl_file_obj *)fod,&foff);

    mfl_free (buf);

    return error;

}

//---------------------------------------------------------------------------

// -                    PE32_write_file_pad_offset                            -

// -                                                                          -

// - Pad file with zero from a certain offset to another offset               -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_write_file_pad_offset (PE32_file_object *fod,

                                                PE32_offset file_ptr,

                                                PE32_offset offset)

{

    char *buf;

    PE32_size size;

    mfl_err error;

    //  calculate fill size

    size = offset - file_ptr;

    //  allocate and reset pad buffer

    if ((buf = mfl_malloc (size)) == NULL)

        return MFL_ERR_NOT_ENOUGH_MEMORY;

    memset (buf, 0, size);

    //  write the pad buffer

    error = mfl_write (buf, size, (mfl_file_obj *)fod);

    //  free pad buffer

    mfl_free (buf);

    return error;

}

//---------------------------------------------------------------------------

// -                       PE32_open_for_write                                -

// -                                                                          -

// - Open file for write if needed. Complete reading file content first if    -

// - the file was initialy opened for read.                                   -

// ---------------------------------------------------------------------------

static FUNC mfl_err PE32_open_for_write (PE32_file_object *fod, mfl_str name)

{

    mfl_err    error;

    mfl_file_p pfout;

    if (fod->mflfh.write_open == TRUE) {

        return MFL_OK;

    }

    //  if file is open for read - read all file content and close it

    if ((error = PE32_read_all_cfile (fod)) != MFL_OK) {

        return error;

    }

    if ((error = mfl_open_normal_or_fd_file (name, 0, &pfout, MFL_OPEN_WRITE_STD

)) != MFL_OK) {

        return error;

    }

    mfl_file_header(fod)->mflfh.write_open = TRUE;

    mfl_file_header(fod)->mflfh.file_open = TRUE;

    mfl_file_header(fod)->mflfh.open_with_fd = FALSE;

    //  mark that for now this file does not used with mmap

    mfl_file_header(fod)->mflfh.used_mmap = FALSE;

    mfl_file_header(fod)->mflfh.fhandle = pfout;

    //  insert the file to the open file list

    if ((error = mfl_insert_new_open_file((mfl_file_obj *)fod)) != MFL_OK) {

        return error;

    }

    return MFL_OK;

}