Ignore:
Timestamp:
Nov 22, 1999, 9:35:52 PM (26 years ago)
Author:
sandervl
Message:

Rewrite of PE loader code, EB's fixes + VirtualProtect bugfix

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/winimagepeldr.cpp

    r1720 r1811  
    1 /* $Id: winimagepeldr.cpp,v 1.13 1999-11-13 15:41:11 sandervl Exp $ */
     1/* $Id: winimagepeldr.cpp,v 1.14 1999-11-22 20:35:52 sandervl Exp $ */
    22
    33/*
     
    4545#include <win\virtual.h>
    4646#include "oslibdos.h"
     47#include "mmap.h"
    4748
    4849char szErrorTitle[]     = "Odin";
     
    7475    imageVirtBase(-1), realBaseAddress(0), imageVirtEnd(0),
    7576    nrNameExports(0), nrOrdExports(0), nameexports(NULL), ordexports(NULL),
    76     fImgMapping(0)
     77    memmap(NULL), pFixups(NULL)
    7778{
    7879 HFILE  dllfile;
     
    120121Win32PeLdrImage::~Win32PeLdrImage()
    121122{
     123  if(memmap)
     124        delete memmap;
     125
     126  if(hFile) {
     127        OSLibDosClose(hFile);
     128        hFile = 0;
     129  }
     130
    122131  if(realBaseAddress)
    123132        DosFreeMem((PVOID)realBaseAddress);
     
    128137  if(ordexports)
    129138        free(ordexports);
    130 
    131   //SvL: Only happens for images that aren't really loaded (RSRC_LOAD)
    132   if(fImgMapping) CloseHandle(fImgMapping);
    133   fImgMapping = 0;
    134139}
    135140//******************************************************************************
     
    137142BOOL Win32PeLdrImage::init(ULONG reservedMem)
    138143{
    139  LPVOID win32file     = NULL;
    140  ULONG  filesize, ulRead;
     144 LPVOID win32file = NULL;
     145 ULONG  filesize, ulRead, ulNewPos;
    141146 PIMAGE_SECTION_HEADER psh;
    142147 IMAGE_SECTION_HEADER sh;
     
    144149 int    nSections, i;
    145150 char   szFullPath[CCHMAXPATH] = "";
    146 
    147   fImgMapping = VIRTUAL_MapFileA(szFileName, &win32file);
    148 
    149   if (fImgMapping == -1) {
    150         strcpy(szErrorModule, OSLibStripPath(szFileName));
     151 IMAGE_DOS_HEADER doshdr;
     152 ULONG  signature;
     153
     154  hFile = OSLibDosOpen(szFileName, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE);
     155
     156  //default error:
     157  strcpy(szErrorModule, OSLibStripPath(szFileName));
     158  if(hFile == NULL) {
    151159        goto failure;
    152160  }
    153 
    154   if(DosQueryPathInfo(szFileName, FIL_QUERYFULLNAME, szFullPath, sizeof(szFullPath)) == 0) {
    155         setFullPath(szFullPath);
    156   }
    157 
    158   if(GetPEFileHeader (win32file, &fh) == FALSE) {
     161  //read dos header
     162  if(DosRead(hFile, (LPVOID)&doshdr, sizeof(doshdr), &ulRead)) {
     163        goto failure;
     164  }
     165  if(OSLibDosSetFilePtr(hFile, doshdr.e_lfanew, OSLIB_SETPTR_FILE_BEGIN) == -1) {
     166        goto failure;
     167  }
     168  //read signature dword
     169  if(DosRead(hFile, (LPVOID)&signature, sizeof(signature), &ulRead)) {
     170        goto failure;
     171  }
     172  //read pe header
     173  if(DosRead(hFile, (LPVOID)&fh, sizeof(fh), &ulRead)) {
     174        goto failure;
     175  }
     176  //read optional header
     177  if(DosRead(hFile, (LPVOID)&oh, sizeof(oh), &ulRead)) {
     178        goto failure;
     179  }
     180  if(doshdr.e_magic != IMAGE_DOS_SIGNATURE || signature != IMAGE_NT_SIGNATURE) {
    159181        fout << "Not a valid PE file (probably a 16 bits windows exe/dll)!" << endl;
    160182        WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szPEErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE);
    161183        goto failure;
     184  }
     185
     186  if(oh.SizeOfImage == 0) {//just in case
     187        oh.SizeOfImage = OSLibDosGetFileSize(hFile);
     188  }
     189
     190  imageSize = oh.SizeOfImage;
     191  //Allocate memory told hold the entire image
     192  if(allocSections(reservedMem) == FALSE) {
     193        fout << "Failed to allocate image memory, rc " << errorState << endl;
     194        goto failure;
     195  }
     196
     197  memmap = new Win32MemMap(this, realBaseAddress, imageSize);
     198  if(memmap == NULL || !memmap->Init(0)) {
     199        strcpy(szErrorModule, OSLibStripPath(szFileName));
     200        goto failure;
     201  }
     202  win32file = memmap->mapViewOfFile(0, 0, 2);
     203
     204  if(DosQueryPathInfo(szFileName, FIL_QUERYFULLNAME, szFullPath, sizeof(szFullPath)) == 0) {
     205        setFullPath(szFullPath);
    162206  }
    163207
     
    183227  }
    184228
    185   GetPEOptionalHeader (win32file, &oh);
    186229  fout << "PE file           : " << szFileName << endl;
    187230  fout << "PE Optional header: " << endl;
     
    200243  fout << "FileAlignment     : " << oh.FileAlignment << endl;
    201244  fout << "Subsystem         : " << oh.Subsystem << endl;
     245  fout << "Image Size        : " << oh.SizeOfImage << endl;
     246  fout << "Header Size       : " << oh.SizeOfHeaders << endl;
     247
     248  //get header page
     249  commitPage(realBaseAddress, FALSE);
    202250
    203251  nSections = NR_SECTIONS(win32file);
     
    205253  if(loadType == REAL_LOAD)
    206254  {
     255   imageSize = 0;
    207256   if ((psh = (PIMAGE_SECTION_HEADER)SECTIONHDROFF (win32file)) != NULL) {
    208257    fout << endl << "*************************PE SECTIONS START**************************" << endl;
     
    215264        if(strcmp(psh[i].Name, ".reloc") == 0) {
    216265            fout << ".reloc" << endl << endl;
    217             addSection(SECTION_RELOC, (char *)win32file+psh[i].PointerToRawData,
     266            addSection(SECTION_RELOC, psh[i].PointerToRawData,
    218267                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    219268                   psh[i].Misc.VirtualSize);
     
    222271        if(strcmp(psh[i].Name, ".edata") == 0) {
    223272            fout << ".edata" << endl << endl;
    224             addSection(SECTION_EXPORT, (char *)win32file+psh[i].PointerToRawData,
     273            addSection(SECTION_EXPORT, psh[i].PointerToRawData,
    225274                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    226275                   psh[i].Misc.VirtualSize);
     
    229278        if(strcmp(psh[i].Name, ".rsrc") == 0) {
    230279            fout << ".rsrc" << endl << endl;
    231             addSection(SECTION_RESOURCE, (char *)win32file+psh[i].PointerToRawData,
     280            addSection(SECTION_RESOURCE, psh[i].PointerToRawData,
    232281                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    233282                   psh[i].Misc.VirtualSize);
     
    243292                        fout << "TLS SizeOfZeroFill       " << hex(tlsDir->SizeOfZeroFill) << endl;
    244293                        fout << "TLS Characteristics      " << hex(tlsDir->Characteristics) << endl;
    245                         addSection(SECTION_TLS, (char *)win32file+psh[i].PointerToRawData,
     294                        addSection(SECTION_TLS, psh[i].PointerToRawData,
    246295                                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    247296                                   psh[i].Misc.VirtualSize);
     
    252301        if(strcmp(psh[i].Name, ".debug") == 0) {
    253302            fout << ".rdebug" << endl << endl;
    254             addSection(SECTION_DEBUG, (char *)win32file+psh[i].PointerToRawData,
     303            addSection(SECTION_DEBUG,  psh[i].PointerToRawData,
    255304                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    256305                   psh[i].Misc.VirtualSize);
     
    265314                type |= SECTION_CODE;
    266315            }
    267             addSection(type, (char *)win32file+psh[i].PointerToRawData,
     316            addSection(type, psh[i].PointerToRawData,
    268317                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    269318                   psh[i].Misc.VirtualSize);
     
    278327        {
    279328            fout << "Code Section" << endl << endl;
    280             addSection(SECTION_CODE, (char *)win32file+psh[i].PointerToRawData,
     329            addSection(SECTION_CODE, psh[i].PointerToRawData,
    281330                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    282331                   psh[i].Misc.VirtualSize);
     
    285334        if(!(psh[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { //read only data section
    286335            fout << "Read Only Data Section" << endl << endl;
    287             addSection(SECTION_READONLYDATA, (char *)win32file+psh[i].PointerToRawData,
     336            addSection(SECTION_READONLYDATA, psh[i].PointerToRawData,
    288337                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    289338                   psh[i].Misc.VirtualSize);
     
    292341        if(psh[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
    293342            fout << "Uninitialized Data Section" << endl << endl;
    294             addSection(SECTION_UNINITDATA, (char *)win32file+psh[i].PointerToRawData,
     343            addSection(SECTION_UNINITDATA, psh[i].PointerToRawData,
    295344                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    296345                   psh[i].Misc.VirtualSize);
     
    299348        if(psh[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) {
    300349            fout << "Initialized Data Section" << endl << endl;
    301             addSection(SECTION_INITDATA, (char *)win32file+psh[i].PointerToRawData,
     350            addSection(SECTION_INITDATA, psh[i].PointerToRawData,
    302351                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    303352                   psh[i].Misc.VirtualSize);
     
    306355        if(psh[i].Characteristics & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ)) {
    307356            fout << "Other Section, stored as read/write uninit data" << endl << endl;
    308             addSection(SECTION_UNINITDATA, (char *)win32file+psh[i].PointerToRawData,
     357            addSection(SECTION_UNINITDATA, psh[i].PointerToRawData,
    309358                   psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase,
    310359                   psh[i].Misc.VirtualSize);
     
    319368        if(GetSectionHdrByName (win32file, &sh, ".rsrc"))
    320369        {
    321             addSection(SECTION_RESOURCE, (char *)win32file+sh.PointerToRawData,
     370            addSection(SECTION_RESOURCE, sh.PointerToRawData,
    322371                       sh.SizeOfRawData, sh.VirtualAddress + oh.ImageBase,
    323372                       sh.Misc.VirtualSize);
     
    335384        imageSize = imageVirtEnd - oh.ImageBase;
    336385  }
    337   if(allocSections(reservedMem) == FALSE) {
    338         fout << "Failed to allocate image memory, rc " << errorState << endl;
    339         goto failure;
    340   }
     386  if(imageSize < oh.SizeOfImage) {
     387        imageSize = oh.SizeOfImage;
     388  }
     389
    341390  fout << "OS/2 base address " << realBaseAddress << endl;
    342   if(storeSections((char *)win32file) == FALSE) {
    343         fout << "Failed to store sections, rc " << errorState << endl;
    344         goto failure;
    345   }
    346391  if(oh.AddressOfEntryPoint) {
    347392        entryPoint = realBaseAddress + oh.AddressOfEntryPoint;
     
    350395        fout << "EntryPoint == NULL" << endl;
    351396        entryPoint = NULL;
     397  }
     398
     399  //set memory protection flags
     400  if(setMemFlags() == FALSE) {
     401        fout << "Failed to set memory protection" << endl;
     402        goto failure;
    352403  }
    353404
     
    361412                goto failure;
    362413        }
    363         setTLSAddress((char *)(sect->realvirtaddr + (tlsDir->StartAddressOfRawData - sect->virtaddr)));
     414        setTLSAddress((char *)sect->realvirtaddr);
    364415        setTLSInitSize(tlsDir->EndAddressOfRawData - tlsDir->StartAddressOfRawData);
    365416        setTLSTotalSize(tlsDir->EndAddressOfRawData - tlsDir->StartAddressOfRawData + tlsDir->SizeOfZeroFill);
     
    381432
    382433   if(realBaseAddress != oh.ImageBase) {
    383         if(setFixups((PIMAGE_BASE_RELOCATION)ImageDirectoryOffset(win32file, IMAGE_DIRECTORY_ENTRY_BASERELOC)) == FALSE) {
    384                 fout << "Failed to set fixups" << endl;
    385                 goto failure;
    386         }
     434        pFixups = (PIMAGE_BASE_RELOCATION)ImageDirectoryOffset(win32file, IMAGE_DIRECTORY_ENTRY_BASERELOC);
     435        commitPage((ULONG)pFixups, FALSE);
    387436   }
    388437   if(fh.Characteristics & IMAGE_FILE_DLL) {
     
    394443  }
    395444
     445  for (i=0; i<nSections; i++) {
     446        commitPage((ULONG)section[i].realvirtaddr, FALSE, COMPLETE_SECTION);
     447  }
     448
    396449  //SvL: Use pointer to image header as module handle now. Some apps needs this
    397450  hinstance = (HINSTANCE)realBaseAddress;
     
    413466  }
    414467 
    415   //set final memory protection flags (storeSections sets them to read/write)
    416   if(setMemFlags() == FALSE) {
    417         fout << "Failed to set memory protection" << endl;
    418         goto failure;
    419   }
    420   CloseHandle(fImgMapping);
    421   fImgMapping = 0;
    422 
    423468  return(TRUE);
    424469failure:
    425   if(fImgMapping) CloseHandle(fImgMapping);
    426   fImgMapping = 0;
     470  if(memmap) {
     471        delete memmap;
     472        memmap = NULL;
     473  }
     474  if(hFile) {
     475        OSLibDosClose(hFile);
     476        hFile = 0;
     477  }
    427478  errorState = ERROR_INTERNAL;
    428479  return FALSE;
    429480}
    430481//******************************************************************************
    431 //******************************************************************************
    432 void Win32PeLdrImage::addSection(ULONG type, char *rawdata, ULONG rawsize, ULONG virtaddress, ULONG virtsize)
     482//commits image page(s) when an access violation exception is dispatched
     483//virtAddress = address of exception (rounded down to page boundary)
     484//******************************************************************************
     485BOOL Win32PeLdrImage::commitPage(ULONG virtAddress, BOOL fWriteAccess, int fPageCmd)
     486{
     487 Section *section;
     488 ULONG    offset, size, sectionsize, protflags, fileoffset, range, attr;
     489 ULONG    ulNewPos, ulRead;
     490 APIRET   rc;
     491
     492  rc = DosQueryMem((PVOID)virtAddress, &range, &attr);
     493  if(rc) {
     494        dprintf(("Win32PeLdrImage::commitPage: DosQueryMem returned %d", rc));
     495        return FALSE;
     496  }
     497  if(attr & PAG_COMMIT) {
     498        dprintf(("Win32PeLdrImage::commitPage: Memory at 0x%x already committed!", virtAddress));
     499        return FALSE;
     500  }
     501
     502  section = findSectionByOS2Addr(virtAddress);
     503  if(section == NULL) {
     504        size        = 4096;
     505        sectionsize = 4096;
     506        protflags   = PAG_READ|PAG_WRITE; //readonly?
     507        section = findPreviousSectionByOS2Addr(virtAddress);
     508        if(section == NULL) {//access to header
     509                fileoffset = virtAddress - realBaseAddress;
     510        }
     511        else {
     512                offset = virtAddress - (section->realvirtaddr + section->virtualsize);
     513                fileoffset = section->rawoffset + section->rawsize + offset;
     514        }
     515  } 
     516  else {
     517        protflags   = section->pageflags;
     518        offset      = virtAddress - section->realvirtaddr;
     519        sectionsize = section->virtualsize - offset;
     520        if(offset > section->rawsize) {
     521                //unintialized data (set to 0)
     522                size = 0;
     523                fileoffset = -1;
     524        } 
     525        else {
     526                size = section->rawsize-offset;
     527                fileoffset = section->rawoffset + offset;
     528        }
     529        if(fWriteAccess & !(section->pageflags & PAG_WRITE)) {
     530                dprintf(("Win32PeLdrImage::commitPage: No write access to 0%x!", virtAddress));
     531                return FALSE;
     532        }
     533  }
     534  if(fPageCmd == SINGLE_PAGE) {
     535        size = min(size, PAGE_SIZE);
     536        sectionsize = min(sectionsize, PAGE_SIZE);
     537  }
     538  else
     539  if(fPageCmd == SECTION_PAGES) {
     540        size = min(size, DEFAULT_NR_PAGES*PAGE_SIZE);
     541        sectionsize = min(sectionsize, DEFAULT_NR_PAGES*PAGE_SIZE);
     542  }
     543  size = min(size, range);
     544  sectionsize = min(sectionsize, range);
     545
     546  if(fileoffset != -1) {
     547        rc = DosSetMem((PVOID)virtAddress, sectionsize, PAG_READ|PAG_WRITE|PAG_COMMIT);
     548        if(rc) {
     549                dprintf(("Win32PeLdrImage::commitPage: DosSetMem failed (%d)!", rc));
     550                return FALSE;
     551        }
     552
     553        if(DosSetFilePtr(hFile, fileoffset, FILE_BEGIN, &ulNewPos) == -1) {
     554                dprintf(("Win32PeLdrImage::commitPage: DosSetFilePtr failed for 0x%x!", fileoffset));
     555                return FALSE;
     556        }
     557        if(DosRead(hFile, (PVOID)virtAddress, size, &ulRead)) {
     558                dprintf(("Win32PeLdrImage::commitPage: DosRead failed for 0x%x!", virtAddress));
     559                return FALSE;
     560        }
     561        if(ulRead != size) {
     562                dprintf(("Win32PeLdrImage::commitPage: DosRead failed to read %x (%x) bytes for 0x%x!", size, ulRead, virtAddress));
     563                return FALSE;
     564        }
     565        if(realBaseAddress != oh.ImageBase) {
     566                setFixups(virtAddress, sectionsize);
     567        }
     568
     569        rc = DosSetMem((PVOID)virtAddress, sectionsize, protflags);
     570        if(rc) {
     571                dprintf(("Win32PeLdrImage::commitPage: DosSetMem failed (%d)!", rc));
     572                return FALSE;
     573        }
     574  }
     575  else {
     576        rc = DosSetMem((PVOID)virtAddress, sectionsize, PAG_READ|PAG_WRITE|PAG_COMMIT);
     577        if(rc) {
     578                dprintf(("Win32PeLdrImage::commitPage: DosSetMem failed (%d)!", rc));
     579                return FALSE;
     580        }
     581        if(realBaseAddress != oh.ImageBase) {
     582                setFixups(virtAddress, sectionsize);
     583        }
     584        rc = DosSetMem((PVOID)virtAddress, sectionsize, protflags);
     585        if(rc) {
     586                dprintf(("Win32PeLdrImage::commitPage: DosSetMem failed (%d)!", rc));
     587                return FALSE;
     588        }
     589  }
     590  return TRUE;
     591}
     592//******************************************************************************
     593//******************************************************************************
     594void Win32PeLdrImage::addSection(ULONG type, ULONG rawoffset, ULONG rawsize, ULONG virtaddress, ULONG virtsize)
    433595{
    434596  virtsize = max(rawsize, virtsize);
    435597
     598  section[nrsections].rawoffset      = rawoffset;
    436599  section[nrsections].type           = type;
    437   section[nrsections].rawdata        = rawdata;
    438600  section[nrsections].rawsize        = rawsize;
    439601  section[nrsections].virtaddr       = virtaddress;
     
    458620
    459621  if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
    460         fout << "No fixups, might not run!" << endl;
    461622        return allocFixedMem(reservedMem);
    462623  }
    463   rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | flAllocMem);
     624  rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | PAG_WRITE | flAllocMem);
    464625  if(rc) {
     626        dprintf(("Win32PeLdrImage::allocSections, DosAllocMem returned %d", rc));
    465627        errorState = rc;
    466628        return(FALSE);
     
    490652  }
    491653  return NULL;
     654}
     655//******************************************************************************
     656//******************************************************************************
     657Section *Win32PeLdrImage::findSectionByOS2Addr(ULONG addr)
     658{
     659  for(int i=0;i<nrsections;i++) {
     660        if(section[i].realvirtaddr <= addr && section[i].realvirtaddr + section[i].virtualsize > addr) {
     661                return &section[i];
     662        }
     663  }
     664  return NULL;
     665}
     666//******************************************************************************
     667//******************************************************************************
     668Section *Win32PeLdrImage::findPreviousSectionByOS2Addr(ULONG addr)
     669{
     670 ULONG lowestAddr = 0xffffffff;
     671 ULONG index = -1;
     672
     673  for(int i=0;i<nrsections;i++) {
     674        if(section[i].realvirtaddr > addr) {
     675                if(section[i].realvirtaddr < lowestAddr) {
     676                        lowestAddr = section[i].realvirtaddr;
     677                        index = i;
     678                }
     679        }
     680  }
     681  if(index == -1)
     682        return NULL;
     683
     684  return &section[index];
    492685}
    493686//******************************************************************************
     
    503696 ULONG  diff, i, baseAddress;
    504697 APIRET rc;
     698 BOOL   allocFlags = flAllocMem;
    505699
    506700  realBaseAddress = 0;
     
    521715  }
    522716
     717  if(oh.ImageBase < 512*1024*124) {
     718        allocFlags = 0;
     719  }
    523720  while(TRUE) {
    524         rc = DosAllocMem((PPVOID)&address, FALLOC_SIZE, PAG_READ | flAllocMem);
     721        rc = DosAllocMem((PPVOID)&address, FALLOC_SIZE, PAG_READ | allocFlags);
    525722        if(rc) break;
    526723
     
    536733                diff = oh.ImageBase - address;
    537734                if(diff) {
    538                         rc = DosAllocMem((PPVOID)&address, diff, PAG_READ | flAllocMem);
     735                        rc = DosAllocMem((PPVOID)&address, diff, PAG_READ | allocFlags);
    539736                        if(rc) break;
    540737                }
    541                 rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | flAllocMem);
     738                rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | PAG_WRITE | allocFlags);
    542739                if(rc) break;
    543740
     
    561758//******************************************************************************
    562759//******************************************************************************
    563 BOOL Win32PeLdrImage::storeSections(char *win32file)
     760BOOL Win32PeLdrImage::setMemFlags()
    564761{
    565762 int i;
    566  APIRET rc;
    567  ULONG  pagFlags = PAG_COMMIT;
    568  ULONG  headersize;
    569763 WINIMAGE_LOOKUP *imgLookup;
    570764
    571   //Commit memory for image header
    572   headersize = sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) +
    573                sizeof(IMAGE_SECTION_HEADER) * fh.NumberOfSections;
    574 
    575   if(headersize + sizeof(WINIMAGE_LOOKUP) < PAGE_SIZE) {
    576         headersize = PAGE_SIZE;
    577   }
    578   else {//ooops, just in case this doesn't work
    579         fout << "ERROR: storeSections: header too big!!!!!! Fatal error" << endl;
    580         return FALSE;
    581   }
    582 
    583   rc = DosSetMem((PVOID)realBaseAddress, headersize, pagFlags | PAG_WRITE | PAG_READ);
    584   if(rc) {
    585         fout << "DosSetMem failed for Image header! " << rc << endl;
    586         return FALSE;
    587   }
    588   // Store the NT header at the load addr
    589   memcpy((char *)realBaseAddress, win32file, sizeof(IMAGE_DOS_HEADER));
    590   memcpy((char *)PE_HEADER(realBaseAddress), PE_HEADER(win32file), sizeof(IMAGE_NT_HEADERS));
    591   memcpy(PE_SECTIONS(realBaseAddress), PE_SECTIONS(win32file),
    592          sizeof(IMAGE_SECTION_HEADER) * fh.NumberOfSections );
    593 
    594765  imgLookup = WINIMAGE_LOOKUPADDR(realBaseAddress);
    595   imgLookup->image = this;
    596 #ifdef DEBUG
    597   imgLookup->magic = MAGIC_WINIMAGE;
    598 #endif
     766  imgLookup->magic1 = MAGIC_WINIMAGE;
     767  imgLookup->image  = this;
     768  imgLookup->magic2 = MAGIC_WINIMAGE;
    599769
    600770  // Process all the image sections
     
    602772        section[i].realvirtaddr = realBaseAddress + (section[i].virtaddr - oh.ImageBase);
    603773  }
     774
    604775  for(i=0;i<nrsections;i++) {
    605         pagFlags = PAG_COMMIT;
    606         switch(section[i].type) {
     776        switch(section[i].type)
     777        {
    607778        case SECTION_CODE:
    608779        case (SECTION_CODE | SECTION_IMPORT):
    609         case SECTION_INITDATA:
    610         case SECTION_UNINITDATA:
    611         case SECTION_IMPORT:
    612         case SECTION_READONLYDATA:
    613         case SECTION_RESOURCE:
    614         case SECTION_TLS:
    615                 pagFlags |= PAG_WRITE | PAG_READ;
    616                 break;
    617         case SECTION_EXPORT:
    618         case SECTION_DEBUG:
    619         case SECTION_RELOC:
    620                 pagFlags = 0;   //don't commit
    621                 break;
    622         }
    623         if(pagFlags == 0)   continue;   //debug or export section
    624 
    625         rc = DosSetMem((PVOID)section[i].realvirtaddr, section[i].virtualsize, pagFlags);
    626         if(rc) {
    627                 errorState = rc;
    628                 return(FALSE);
    629         }
    630         if(section[i].type != SECTION_UNINITDATA) {
    631                 assert(section[i].rawdata);
    632                 memcpy((char *)section[i].realvirtaddr, section[i].rawdata, section[i].rawsize);
    633         }
    634   }
    635   return(TRUE);
    636 }
    637 //******************************************************************************
    638 //******************************************************************************
    639 BOOL Win32PeLdrImage::setMemFlags()
    640 {
    641  int i;
    642  APIRET rc;
    643  ULONG  pagFlags = 0;
    644 
    645   for(i=0;i<nrsections;i++) {
    646         pagFlags = 0;
    647         switch(section[i].type) {
    648         case SECTION_CODE:
    649         case (SECTION_CODE | SECTION_IMPORT):
    650                 pagFlags |= PAG_EXECUTE | PAG_READ;
     780                section[i].pageflags = PAG_EXECUTE | PAG_READ;
    651781                break;
    652782        case SECTION_INITDATA:
    653783        case SECTION_UNINITDATA:
    654784        case SECTION_IMPORT: //TODO: read only?
    655                 pagFlags |= PAG_WRITE | PAG_READ;
     785                section[i].pageflags = PAG_WRITE | PAG_READ;
    656786                break;
    657787        case SECTION_READONLYDATA:
    658788        case SECTION_RESOURCE:
    659789        case SECTION_TLS:
    660                 pagFlags |= PAG_READ;
     790        default:
     791                section[i].pageflags = PAG_READ;
    661792                break;
    662         default:
    663                 continue;
    664793        }
    665         rc = DosSetMem((PVOID)section[i].realvirtaddr, section[i].virtualsize, pagFlags);
    666         if(rc) {
    667                 errorState = rc;
    668                 return(FALSE);
    669         }
     794  }
     795  return(TRUE);
     796}
     797//******************************************************************************
     798//******************************************************************************
     799BOOL Win32PeLdrImage::setFixups(ULONG virtAddress, ULONG size)
     800{
     801 int   i, j;
     802 char *page;
     803 ULONG count, newpage;
     804 Section *section;
     805 PIMAGE_BASE_RELOCATION prel = pFixups;
     806
     807  if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
     808        return(TRUE);
     809  }
     810
     811  virtAddress -= realBaseAddress;
     812
     813  if(prel) {
     814        j = 1;
     815        while(prel->VirtualAddress && prel->VirtualAddress < virtAddress) {
     816                prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock);
     817        }
     818        while(prel->VirtualAddress && prel->VirtualAddress < virtAddress + size) {
     819                page = (char *)((char *)prel + (ULONG)prel->VirtualAddress);
     820                count  = (prel->SizeOfBlock - 8)/2;
     821                j++;
     822                for(i=0;i<count;i++) {
     823                        int type   = prel->TypeOffset[i] >> 12;
     824                        int offset = prel->TypeOffset[i] & 0xFFF;
     825                        int fixupsize = 0;
     826
     827                        switch(type)
     828                        {
     829                        case IMAGE_REL_BASED_HIGHLOW:
     830                                fixupsize = 4;
     831                                break;
     832                        case IMAGE_REL_BASED_HIGH:
     833                        case IMAGE_REL_BASED_LOW:
     834                                fixupsize = 2;
     835                                break;
     836                        }                       
     837                        //If the fixup crosses the final page boundary,
     838                        //then we have to load another page
     839                        if(prel->VirtualAddress + offset + fixupsize > virtAddress + size)
     840                        {
     841                                newpage  = realBaseAddress + prel->VirtualAddress + offset + fixupsize;
     842                                newpage &= ~0xFFF;
     843
     844                                section  = findSectionByOS2Addr(newpage);
     845                                if(section == NULL) {
     846                                        //should never happen
     847                                        dprintf(("::setFixups -> section == NULL!!"));
     848                                        return FALSE;
     849                                }               
     850                                //SvL: Read page from disk
     851                                commitPage(newpage, TRUE, SINGLE_PAGE);
     852
     853                                //SvL: Enable write access
     854                                DosSetMem((PVOID)newpage, PAGE_SIZE, PAG_READ|PAG_WRITE);
     855                        }
     856
     857                        switch(type)
     858                        {
     859                        case IMAGE_REL_BASED_ABSOLUTE:
     860                                break;  //skip
     861                        case IMAGE_REL_BASED_HIGHLOW:
     862                                AddOff32Fixup(prel->VirtualAddress + offset);
     863                                break;
     864                        case IMAGE_REL_BASED_HIGH:
     865                                AddOff16Fixup(prel->VirtualAddress + offset, TRUE);
     866                                break;
     867                        case IMAGE_REL_BASED_LOW:
     868                                AddOff16Fixup(prel->VirtualAddress + offset, FALSE);
     869                                break;
     870                        case IMAGE_REL_BASED_HIGHADJ:
     871                        case IMAGE_REL_BASED_MIPS_JMPADDR:
     872                        default:
     873                                break;
     874                        }
     875                        if(prel->VirtualAddress + offset + fixupsize > virtAddress + size)
     876                        {
     877                                //SvL: Restore original page protection flags
     878                                DosSetMem((PVOID)newpage, PAGE_SIZE, section->pageflags);
     879                        }
     880
     881                }
     882                prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock);
     883        }//while
     884  }
     885  else {
     886        dprintf(("Win32PeLdrImage::setFixups, no fixups at %x, %d", virtAddress, size));
     887        return(FALSE);
    670888  }
    671889  return(TRUE);
     
    680898
    681899  if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) {
    682     return(TRUE);
     900        return(TRUE);
    683901  }
    684902
     
    701919            case IMAGE_REL_BASED_HIGHLOW:
    702920////                fout << "address " << offset << " type " << type << endl;
    703                 AddOff32Fixup(oh.ImageBase +
    704                           prel->VirtualAddress + offset);
     921                AddOff32Fixup(prel->VirtualAddress + offset);
    705922                break;
    706923            case IMAGE_REL_BASED_HIGH:
    707                 AddOff16Fixup(oh.ImageBase + prel->VirtualAddress + offset, TRUE);
     924                AddOff16Fixup(prel->VirtualAddress + offset, TRUE);
    708925                break;
    709926            case IMAGE_REL_BASED_LOW:
    710                 AddOff16Fixup(oh.ImageBase + prel->VirtualAddress + offset, FALSE);
     927                AddOff16Fixup(prel->VirtualAddress + offset, FALSE);
    711928                break;
    712929            case IMAGE_REL_BASED_HIGHADJ:
     
    734951 ULONG *fixup;
    735952
    736   fixup   = (ULONG *)(fixupaddr - oh.ImageBase + realBaseAddress);
     953  fixup   = (ULONG *)(fixupaddr + realBaseAddress);
    737954  orgaddr = *fixup;
    738955  *fixup  = realBaseAddress + (*fixup - oh.ImageBase);
     
    745962 USHORT *fixup;
    746963
    747   fixup   = (USHORT *)(fixupaddr - oh.ImageBase + realBaseAddress);
     964  fixup   = (USHORT *)(fixupaddr + realBaseAddress);
    748965  orgaddr = *fixup;
    749966  if(fHighFixup) {
     
    761978 ULONG  apiaddr;
    762979
    763   import  = (ULONG *)(impaddr - oh.ImageBase + realBaseAddress);
     980  import  = (ULONG *)impaddr;
    764981  apiaddr = WinDll->getApi(ordinal);
    765982  if(apiaddr == 0)
    766983  {
    767     dprintf(("KERNEL32:Win32PeLdrImage - %s.%u not found\n",
    768              WinDll->getName(),
    769              ordinal));
     984        dprintf(("KERNEL32:Win32PeLdrImage - %s.%u not found\n",
     985                 WinDll->getName(),
     986                 ordinal));
    770987
    771988        fout << "--->>> NOT FOUND!" << endl;
     
    781998 ULONG  apiaddr;
    782999
    783   import = (ULONG *)(impaddr - oh.ImageBase + realBaseAddress);
     1000  import = (ULONG *)impaddr;
    7841001  apiaddr = WinDll->getApi(impname);
    7851002  if(apiaddr == 0)
    7861003  {
    787     dprintf(("KERNEL32:Win32PeLdrImage - %s.%s not found\n",
    788              WinDll->getName(),
    789              impname));
     1004        dprintf(("KERNEL32:Win32PeLdrImage - %s.%s not found\n",
     1005                WinDll->getName(),
     1006                impname));
    7901007
    7911008        fout << "--->>> NOT FOUND!" << endl;
     
    8101027
    8111028        fout << "Exported Functions: " << endl;
    812     ptrOrd     = (USHORT *)((ULONG)ped->AddressOfNameOrdinals -
    813                     (ULONG)sh.VirtualAddress +
    814                             (ULONG)sh.PointerToRawData + (ULONG)win32file);
    815     ptrNames   = (ULONG *)((ULONG)ped->AddressOfNames -
    816                   (ULONG)sh.VirtualAddress +
    817                           (ULONG)sh.PointerToRawData + (ULONG)win32file);
    818     ptrAddress = (ULONG *)((ULONG)ped->AddressOfFunctions -
    819                   (ULONG)sh.VirtualAddress +
    820                           (ULONG)sh.PointerToRawData + (ULONG)win32file);
     1029    ptrOrd     = (USHORT *)((ULONG)ped->AddressOfNameOrdinals +
     1030                            (ULONG)win32file);
     1031    ptrNames   = (ULONG *)((ULONG)ped->AddressOfNames +
     1032                            (ULONG)win32file);
     1033    ptrAddress = (ULONG *)((ULONG)ped->AddressOfFunctions +
     1034                            (ULONG)win32file);
    8211035    nrOrdExports  = ped->NumberOfFunctions;
    8221036    nrNameExports = ped->NumberOfNames;
     
    8261040    for(i=0;i<ped->NumberOfNames;i++) {
    8271041        ord       = ptrOrd[i] + ped->Base;
    828         name      = (char *)((ULONG)ptrNames[i] - (ULONG)sh.VirtualAddress +
    829                              (ULONG)sh.PointerToRawData + (ULONG)win32file);
     1042        name      = (char *)((ULONG)ptrNames[i] + (ULONG)win32file);
    8301043        RVAExport = ptrAddress[ptrOrd[i]];
    8311044#ifdef FORWARDERS
     
    8331046#endif
    8341047            //points to code (virtual address relative to oh.ImageBase
    835                 fout << "address 0x";
    836                 fout.setf(ios::hex, ios::basefield);
     1048            AddNameExport(oh.ImageBase + RVAExport, name, ord);
     1049            fout << "address 0x";
     1050            fout.setf(ios::hex, ios::basefield);
    8371051            fout << RVAExport;
    838                     fout.setf(ios::dec, ios::basefield);
    839                 fout << " " << name << "@" << ord << endl;
    840             AddNameExport(oh.ImageBase + RVAExport, name, ord);
     1052            fout.setf(ios::dec, ios::basefield);
     1053            fout << " " << name << "@" << ord << endl;
    8411054#ifdef FORWARDERS
    8421055
    8431056        }
    8441057        else {//forwarder
    845             char *forward = (char *)((ULONG)RVAExport -
    846                          (ULONG)sh.VirtualAddress +
    847                                      (ULONG)sh.PointerToRawData +
    848                              (ULONG)win32file);
     1058            char *forward = (char *)((ULONG)RVAExport + (ULONG)win32file);
    8491059            fout << RVAExport << " " << name << " @" << ord << " is forwarder to " << (int)forward << endl;
    8501060        }
     
    8681078        }
    8691079        else {//forwarder or empty
    870             char *forward = (char *)((ULONG)RVAExport -
    871                          (ULONG)sh.VirtualAddress +
    872                                      (ULONG)sh.PointerToRawData +
    873                              (ULONG)win32file);
     1080            char *forward = (char *)((ULONG)RVAExport + (ULONG)win32file);
    8741081            fout << "ord " << ord << " at 0x";
    875                     fout.setf(ios::hex, ios::basefield);
     1082            fout.setf(ios::hex, ios::basefield);
    8761083            fout << RVAExport << " is forwarder to 0x" << (int)forward << endl;
    877                     fout.setf(ios::dec, ios::basefield);
     1084            fout.setf(ios::dec, ios::basefield);
    8781085        }
    8791086#endif
     
    9391146 IMAGE_SECTION_HEADER     shExtra = {0};
    9401147 PIMAGE_OPTIONAL_HEADER   pOH;
    941  int    i,j;
     1148 int    i,j, nrPages;
    9421149 BOOL   fBorland = 0;
    9431150 int    cModules;
     
    9491156 int    Size;
    9501157 Win32PeLdrDll *WinDll;
     1158 Section *section;
    9511159
    9521160/* "algorithm:"
     
    9751183    //test RVA inside ID-Section
    9761184    if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData)) {
    977         pszTmp = (char*)(pID[i].Name- shID.VirtualAddress + shID.PointerToRawData + (ULONG)win32file);
     1185        pszTmp = (char*)(pID[i].Name + (ULONG)win32file);
    9781186    }
    9791187    else {
     
    9831191                 return FALSE;
    9841192        }
    985         pszTmp = (char*)(pID[i].Name- shExtra.VirtualAddress + shExtra.PointerToRawData + (ULONG)win32file);
     1193        pszTmp = (char*)(pID[i].Name + (ULONG)win32file);
    9861194    }
    9871195    Size += strlen(pszTmp) + 1;
     
    9971205    //test RVA inside ID-Section
    9981206    if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData)) {
    999         pszTmp = (char*)(pID[i].Name- shID.VirtualAddress + shID.PointerToRawData + (ULONG)win32file);
     1207        pszTmp = (char*)(pID[i].Name + (ULONG)win32file);
    10001208    }
    10011209    else {
     
    10091217            }
    10101218        }
    1011         pszTmp = (char*)(pID[i].Name- shExtra.VirtualAddress + shExtra.PointerToRawData + (ULONG)win32file);
     1219        pszTmp = (char*)(pID[i].Name + (ULONG)win32file);
    10121220    }
    10131221
     
    10411249    }
    10421250    //light borland-style test
    1043     if (pID[i].u.OriginalFirstThunk == 0 || fBorland)
    1044         pulImport = (ULONG*)pID[i].FirstThunk;
     1251    if (pID[i].u.OriginalFirstThunk == 0 || fBorland) {
     1252            pulImport = (ULONG*)pID[i].FirstThunk;
     1253    }
    10451254    else    pulImport = (ULONG*)pID[i].u.OriginalFirstThunk;
    10461255
     
    11311340    WinDll->AddRef();
    11321341
    1133     pulImport  = (PULONG)((ULONG)pulImport - shExtra.VirtualAddress + (ULONG)win32file + shExtra.PointerToRawData);
     1342    pulImport  = (PULONG)((ULONG)pulImport + (ULONG)win32file);
    11341343    j          = 0;
    1135     ulCurFixup = (ULONG)pID[i].FirstThunk + pOH->ImageBase;
     1344    ulCurFixup = (ULONG)pID[i].FirstThunk + (ULONG)win32file;
     1345
     1346    section    = findSectionByOS2Addr(ulCurFixup);
     1347    if(section == NULL) {
     1348        fout.setf(ios::hex, ios::basefield);
     1349        fout << "Unable to find section for " << ulCurFixup << endl;
     1350        return FALSE;
     1351    }
     1352    //SvL: Read page from disk
     1353    commitPage(ulCurFixup & ~0xfff, FALSE, SINGLE_PAGE);
     1354    //SvL: Enable write access
     1355    DosSetMem((PVOID)(ulCurFixup & ~0xfff), PAGE_SIZE, PAG_READ|PAG_WRITE);
     1356    nrPages    = 1;
     1357
    11361358    while (pulImport[j] != 0) {
    11371359        if (pulImport[j] & IMAGE_ORDINAL_FLAG) { //ordinal
     
    11511373            }
    11521374            //KSO - Aug 6 1998 1:15am:this eases comparing...
    1153             char *pszFunctionName = (char*)(pulImport[j] + (ULONG)win32file + shExtra.PointerToRawData - shExtra.VirtualAddress + 2);
     1375            char *pszFunctionName = (char*)(pulImport[j] + (ULONG)win32file + 2);
    11541376            fout.setf(ios::hex, ios::basefield);
    11551377            fout << "0x" << ulCurFixup << " Imported function " << pszFunctionName << endl;
     
    11571379            StoreImportByName(WinDll, pszFunctionName, ulCurFixup);
    11581380        }
    1159             ulCurFixup += sizeof(IMAGE_THUNK_DATA);
     1381        ulCurFixup += sizeof(IMAGE_THUNK_DATA);
    11601382        j++;
     1383        if((ulCurFixup & 0xfff) == 0) {
     1384                commitPage(ulCurFixup & ~0xfff, TRUE, SINGLE_PAGE);
     1385                DosSetMem((PVOID)(ulCurFixup & ~0xfff), PAGE_SIZE, PAG_READ|PAG_WRITE);
     1386                nrPages++;
     1387        }
    11611388    }
     1389    //SvL: And restore original protection flags
     1390    ulCurFixup = (ULONG)pID[i].FirstThunk + pOH->ImageBase;
     1391    DosSetMem((PVOID)(ulCurFixup & ~0xfff), PAGE_SIZE*nrPages, section->pageflags);
     1392
    11621393    fout << "**********************************************************************" << endl;
    11631394    fout << "************** End Import Module " << pszCurModule << endl;
     
    11841415  do {
    11851416    r = WinMessageBox(HWND_DESKTOP, NULLHANDLE, "The application has called a non-existing api\n",
    1186                   "Internal Error", 0, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION | MB_MOVEABLE);
     1417                  "Internal Odin Error", 0, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION | MB_MOVEABLE);
    11871418  }
    11881419  while(r == MBID_RETRY); //giggle
Note: See TracChangeset for help on using the changeset viewer.