#include "LPEL_Useful.h"
#include "LPEL_Headers.h"

DWORD DLLEXPORT LPEL_GetAlignment(DWORD dwValue, DWORD dwAlignment)
{
      if((dwValue % dwAlignment) == 0)
                  return dwValue;
      else
          return (((dwValue/dwAlignment)+1) * dwAlignment);
}
VOID DLLEXPORT LPEL_RecalcSizeOfImage(HANDLE hBinary)
{
     PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
     PIMAGE_SECTION_HEADER pSectionHeader = NULL;
     PIMAGE_FILE_HEADER pCOFFHeader = NULL;

     DWORD dwSectionAlignment;
     DWORD dwVirtualSizeOfSections = 0x0;
     size_t i;
     
     pOptionalHeader = LPEL_GetOptionalHeader(hBinary);
     pCOFFHeader = LPEL_GetCOFFHeader(hBinary);
     pSectionHeader = LPEL_GetSectionHeader(hBinary);
     
     dwSectionAlignment = pOptionalHeader->SectionAlignment;
     
     for(i = 0; i <= pCOFFHeader->NumberOfSections; i++)
     {
           dwVirtualSizeOfSections += pSectionHeader[i].Misc.VirtualSize;
     }
     
     //Updating SizeOfImage      
     //printf("\n[+]Recalculating SizeOfImage...\n                        SizeOfImage updated from 0x%x to", pOptionalHeader->SizeOfImage);
     pOptionalHeader->SizeOfImage = LPEL_GetAlignment(pOptionalHeader->SizeOfHeaders+dwVirtualSizeOfSections, dwSectionAlignment);
     //printf(" 0x%x", pOptionalHeader->SizeOfImage);
     
     return;
}     
PDWORD DLLEXPORT LPEL_GetRawBaseOfCode(HANDLE hBinary)
{
     PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
     PIMAGE_SECTION_HEADER pSectionHeader = NULL;
     PIMAGE_FILE_HEADER pCOFFHeader = NULL;

     size_t i;
     
     pOptionalHeader = LPEL_GetOptionalHeader(hBinary);
     pCOFFHeader = LPEL_GetCOFFHeader(hBinary);
     pSectionHeader = LPEL_GetSectionHeader(hBinary);
     
     for(i = 0; i <= pCOFFHeader->NumberOfSections; i++)
     {
           //On regarde si le code est bien dans cette section
           if((PDWORD)pOptionalHeader->BaseOfCode >= (PDWORD)pSectionHeader[i].VirtualAddress && (PDWORD)pOptionalHeader->BaseOfCode <= (PDWORD)((PUCHAR)pSectionHeader[i].VirtualAddress + pSectionHeader[i].Misc.VirtualSize))
                                          return (PDWORD)((PUCHAR)pSectionHeader[i].PointerToRawData + pOptionalHeader->BaseOfCode-pSectionHeader[i].VirtualAddress);
                                          //Au cas (très rare)où le code ne débuterait pas au début de la section, on ajoute la différence.
     }
     
     return 0x0;
}
DWORD DLLEXPORT LPEL_GetBinarySize(HANDLE hBinary)
{
     PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
     
     pOptionalHeader = LPEL_GetOptionalHeader(hBinary);
     
     return pOptionalHeader->SizeOfImage;
     
}
PDWORD DLLEXPORT LPEL_RVAtoRAW(HANDLE hBinary, PDWORD pRvaAddr)
{
     PDWORD pRawAddr = NULL;
     PIMAGE_OPTIONAL_HEADER pOptionalHeader = NULL;
     PIMAGE_SECTION_HEADER pSectionHeader = NULL;
     PIMAGE_FILE_HEADER pCOFFHeader = NULL;

     size_t i;
     
     pOptionalHeader = LPEL_GetOptionalHeader(hBinary);
     pCOFFHeader = LPEL_GetCOFFHeader(hBinary);
     pSectionHeader = LPEL_GetSectionHeader(hBinary);
     
     for(i = 0; i <= pCOFFHeader->NumberOfSections; i++)
     {
           //We try to find in which section is situated the RVA Address
           if(pRvaAddr >= (PDWORD)pSectionHeader[i].VirtualAddress && pRvaAddr < (PDWORD)((PUCHAR)pSectionHeader[i].VirtualAddress + pSectionHeader[i].Misc.VirtualSize))
                                          return (PDWORD)((PUCHAR)pRvaAddr - pSectionHeader[i].VirtualAddress + pSectionHeader[i].PointerToRawData);
           
                                               
     }
}
VOID DLLEXPORT LPEL_ReajustRVA(HANDLE hBinary, PDWORD pAddr, PDWORD pOldSectionRVA, PDWORD pNewSectionRVA)
{
     pAddr = (PDWORD)((PUCHAR)pAddr - (DWORD)pOldSectionRVA + (DWORD)pNewSectionRVA);
     return;
     
}