/*
* Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/


#if !defined(__PE_FILE_H__)
#define __PE_FILE_H__
#include <e32rom.h>
#include <e32image.h>
#include "pe_defs.h"
//
const TInt KTextSection=0;
const TInt KConstSection=1;
const TInt KExportSection=2;
const TInt KDataSection=3;
const TInt KBssSection=4;
const TInt KImportSection=5;
const TInt KCrtSection=6;
const TInt KRelocSection=7;
const TInt KNumberOfSections=8;
//
enum TImportStat {EImpError, EImpSuccess, EImpDone};
//
class PEFile
	{
public:
	PEFile();
	~PEFile();
	TBool Init(const TText * const aFileName);
	void Close();
	//
	TImportStat GetNextImport(TText * &aDllName, TUint16 &aOrdinal, TUint32 * &aThunkPtr);
	TUint32 GetFixUp(const TUint16 aOrdinal);
// 	TText *GetImageName();
//	TUint8 *GetExportName(const TUint16 aOrdinal);
//	TUint32 WriteDllRefTable(PEFile aPeArray[], TUint aMaxFiles);
	void RelocateExportTable();
	TUint GetNumberOfExportedFunctions();
	TUint GetOrdinalBase();
	TBool ExportSectionExists();
	TBool ImportSectionExists();
	TUint RoundToSectionSize(TUint aSize);
	void DumpPeHeaders();
	//
	TInt Normalise();
	void GetRelocs(TUint *aReloc, TUint *aRelocSection, TInt aNumberOfRelocs);
	TInt ReadSectionHeaders();
	TInt ReadData();
	TInt ReadExportDirectory();
	char *ReadSectionData(PIMAGE_SECTION_HEADER aHeader);
	TInt NumberOfImports() const;
	TInt NumberOfImportDlls() const;
	TInt NumberOfExports() const;
	TInt NumberOfRelocs();
public:
	static TInt CmpSectionName(PIMAGE_SECTION_HEADER apSectionHeader, char *aName);
	TInt VirtualAddressInSection(TUint aVA, PIMAGE_SECTION_HEADER aHeader);
	TUint DistanceFromSection(TUint aVA, PIMAGE_SECTION_HEADER aHeader);
	TInt FindSectionByVa(TUint aVa, TUint aTryToBeClever=0);
	static TInt HasInitialisedData(PIMAGE_SECTION_HEADER aHeader);
	
//	static TBool DoFixUps(PEFile aPeArray[], TUint aMaxFiles);
//	static TBool FindByName(PEFile aPeArray[], TUint aMaxFiles,const TText * const aDllName, PEFile * &aExportPEFile);
//	static void WriteDllRefTables(PEFile aPeArray[], TUint aMaxFiles);
//	static void RelocateExportTables(PEFile aPeArray[], TUint aMaxFiles);
private:
	TBool IsInCode(TUint32 anAddr);
	TBool IsInData(TUint32 anAddr);
	TBool IsInDataReloc(TUint32 anAddr);
	TBool IsInExport(TUint32 anAddr);
	TBool IsInImport(TUint32 anAddr);
	TBool IsValidDOSHeader(PIMAGE_DOS_HEADER pDOSHeader);
	TBool IsValidNTHeader(PIMAGE_NT_HEADERS pNTHeader);
	TBool IsValidFileHeader(PIMAGE_FILE_HEADER pFileHeader);
	void DumpNextSectionInFile(PIMAGE_SECTION_HEADER pSectionHeader);
	void CopySectionData(TAny *source, TAny *dest, TUint32 fileLength, TUint32 memLength);
	TBool ProcessRelocData(TAny *relocData,TInt dataSize);
	PEFile(const PEFile&);
	const PEFile & operator = (const PEFile&);
public:
	static TUint32 iRomMemBase; // where the ROM is being loaded to
	static TUint32 iRomLinearBase; // where the ROM will run
	TUint32 iMemBase; // where this file is being loaded to
	TUint32 iEntryPoint;
	TUint32 iImageSize;
	TUint32 iCodeSize;
	TUint32 iDataSize;
	TUint32 iHeapReservedSize;
	TUint32 iHeapCommittedSize;
	TUint32 iStackReservedSize;
	TUint32 iStackCommittedSize;
	TUint32 iBssSize;
	TUint32 iBssOffset;
	TUint32 iSectionAlign;
	TUint32 iExpDirectoryOffset;
	TUint32 iDataOffset;
	TBool	iImageIsDll;
private:
	IMAGE_NT_HEADERS *iHeader;
 	PIMAGE_EXPORT_DIRECTORY	iExpDirectory;
	PIMAGE_IMPORT_DESCRIPTOR iImpDescriptor; 
	TText *iFileName;
	TInt32 iFileHandle;
	TUint32 iLinkedBase;
	TUint32 iStartOfHeaders; // whether DOS header or not
	TUint32 iSizeOfHeaders; // Up to and including section headers
	TUint32 iNumSections;
	TUint32 iRomRunAddr; // where the code will run & rdata be accessed
	TUint32 iRamRunAddr; // and where the data & bss will be when it does
	TUint32 iRomDelta;
	TUint32 iRamDelta;
	TBool iHadDataSection;

// stuff for relocating image successfully in 2 parts
	TUint32 iBssSectionLinkedAddr;
	TUint32 iBssSectionAddr;
	TUint32 iBssSectionSize;
	TUint32 iDataSectionLinkedAddr;
	TUint32 iDataSectionAddr;
	TUint32 iDataSectionSize;
	TUint32 iCodeSectionAddr;
	TUint32 iCodeSectionSize;
	TUint32 iRDataSectionAddr;
	TUint32 iRDataSectionSize;
	TUint32 iCRTSectionAddr;
	TUint32 iCRTSectionSize;
	TUint32 iExportDataDir;

// stuff for the pe->e32image translator
	PIMAGE_SECTION_HEADER iSectionHeader[KNumberOfSections];
	char *iSectionData[KNumberOfSections];
	TInt iExportDirSize;
	TInt iCpu;
	friend class E32ImageFile;
	friend class E32ImageFile_PE;
	};

class E32ImageFile_PE : public E32ImageFile
	{
public:
	E32ImageFile_PE();
	virtual ~E32ImageFile_PE();
	virtual TBool Translate(const char* aFileName, TUint aDataBase, TBool aAllowDllData, TBool /*aSymLkupEnabled*/);
	TBool Translate(PEFile &aPEFile);
	TUint ImportAddressTableOffset();
	TUint ConstOffset();
private:
	TInt DoCodeHeader(PEFile &aPeFile);
	TInt DoDataHeader(PEFile &aPeFile, TUint aDataBase);
	TInt CopyCode(char *aPtr, PEFile &aPeFile);
	TInt CopyData(char *aPtr, PEFile &aPeFile);
	TInt CopyImportAddrTable(char *aPtr, PEFile &aPeFile);
	char *CreateImportSection(const PEFile &aPeFile, TInt &aSize);
	void CreateExportSection(char *aPtr, PEFile &aPeFile);

	void CreateExportDirectory(char *aPtr, PEFile &aPeFile);
	void FixExportDirectory(TUint *aExportDir, PEFile &aPeFile);
	void FixRelocs(PEFile &aPeFile, TUint *relocation, TUint *relocsection, TInt aNumberOfRelocs);
	char *CreateCodeRelocs(TUint *reloc, TUint *relocsection, TInt nrelocs, TInt &aSize);
	char *CreateDataRelocs(TUint *reloc, TUint *relocsection, TInt nrelocs, TInt &aSize);

	TUint FixAddress(PEFile &aPeFile, TUint va);
	TUint FixImportThunk(PEFile &aPeFile, TUint va);
private:
	PIMAGE_SECTION_HEADER iPeHeader[KNumberOfSections];
	char *iPeData[KNumberOfSections];
	TUint iConstOffset;
	TUint iCrtOffset;
	};

#endif
