#if !defined(__PEINLINE_H__)            /* { */
#define __PEINLINE_H__

/* -------------------------------------------------------------------------------------------- */
//#include "PEFile.h"


/* -------------------------------------------------------------------------------------------- */
#if defined(__cplusplus)
extern "C" {
#endif

#define IDS_ERRBADFILENAME	1000
#define IDR_CURSOR		1
#define IDR_BITMAP		2
#define IDR_ICON		3
#define IDR_MENU		4
#define IDR_DIALOG		5
#define IDR_STRING		6
#define IDR_FONTDIR		7
#define IDR_FONT		8
#define IDR_ACCELERATOR 	9
#define IDR_RCDATA		10
#define IDR_MESSAGETABLE	11

#define SIZE_OF_NT_SIGNATURE	sizeof (DWORD)
#define MAXRESOURCENAME 	13

/* global macros to define header offsets into file */
/* offset to PE file signature				       */
#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a		     +	\
			((PIMAGE_DOS_HEADER)a)->e_lfanew))

/* DOS header identifies the NT PEFile signature dword
   the PEFILE header exists just after that dword	       */
#define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a		     +	\
			 ((PIMAGE_DOS_HEADER)a)->e_lfanew    +	\
			 SIZE_OF_NT_SIGNATURE))

/* PE optional header is immediately after PEFile header       */
#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a		     +	\
			 ((PIMAGE_DOS_HEADER)a)->e_lfanew    +	\
			 SIZE_OF_NT_SIGNATURE		     +	\
			 sizeof (IMAGE_FILE_HEADER)))

/* section headers are immediately after PE optional header    */
#define SECHDROFFSET(a) ((LPVOID)((BYTE *)a		     +	\
			 ((PIMAGE_DOS_HEADER)a)->e_lfanew    +	\
			 SIZE_OF_NT_SIGNATURE		     +	\
			 sizeof (IMAGE_FILE_HEADER)	     +	\
			 sizeof (IMAGE_OPTIONAL_HEADER)))


typedef struct tagImportDirectory
    {
    DWORD    dwRVAFunctionNameList;
    DWORD    dwUseless1;
    DWORD    dwUseless2;
    DWORD    dwRVAModuleName;
    DWORD    dwRVAFunctionAddressList;
    }IMAGE_IMPORT_MODULE_DIRECTORY, * PIMAGE_IMPORT_MODULE_DIRECTORY;


/* -------------------------------------------------------------------------------------------- */
__inline int __cdecl StringCompareToCryptKey(const char * src,const char * dst)/**/
{
	int ret = 0 ;
	long lKey = *(long*)(dst);
	unsigned char *p_ucCryptKey = (unsigned char*) &lKey;
	unsigned char ucSize = (unsigned char)dst [4];
	unsigned char ucIndex;
	unsigned char ucUncoded;

	dst += 5;
	for (ucIndex = 0 ; ucIndex < ucSize ; ucIndex++)
	{
		// uncode dst char
		ucUncoded = (*(unsigned char *)dst++ - p_ucCryptKey[0]) ^ p_ucCryptKey[1];
		p_ucCryptKey[0] += p_ucCryptKey[2];
		p_ucCryptKey[1] += p_ucCryptKey[3];

		// compare
		ret = *(unsigned char *)src++ - ucUncoded;
		if(ret)	break;
	}

	if ( ret < 0 ) ret = -1 ;
	else if ( ret > 0 ) ret = 1 ;
	return( ret );
}

/* -------------------------------------------------------------------------------------------- */
__inline DWORD dwInternalGetImportedFunctionEntry(DWORD dwImageBase,PIMAGE_IMPORT_MODULE_DIRECTORY pid,LPCSTR lpProcName)
{
	char *lpBuffer=(char*) dwImageBase;
  if ( (lpBuffer) && (pid) )
  {
		// walk through import table name list (DLL)
		while(pid->dwRVAFunctionNameList)
		{
			char *DllNamePtr=(char*) &lpBuffer[pid->dwRVAModuleName];
			DWORD dwRVAFunctionNameList=pid->dwRVAFunctionNameList;
			DWORD dwRVAFunctionAddressList=pid->dwRVAFunctionAddressList;
			DWORD *FunctionNamePtr=(DWORD*) &lpBuffer[dwRVAFunctionNameList];
			DWORD *FunctionAdressPtr=(DWORD*) &lpBuffer[dwRVAFunctionAddressList];

			// walk through DLL func
			while(*FunctionNamePtr)
			{
				// ordinal or not ?
        if (!IMAGE_SNAP_BY_ORDINAL(*FunctionNamePtr))
				{
          PIMAGE_IMPORT_BY_NAME ImportPtr=(PIMAGE_IMPORT_BY_NAME) &lpBuffer[*FunctionNamePtr];
          WORD Hint=ImportPtr->Hint;
          char *NamePtr=(char*) &ImportPtr->Name[0];

          //if (!StringCompare(NamePtr,lpProcName))
		  if (!StringCompareToCryptKey(NamePtr,lpProcName))
					{
						// found what we want
						return((DWORD) FunctionAdressPtr);
					}
				}
				FunctionNamePtr++;
				FunctionAdressPtr++;
			}
			pid++;
		}
	}
	return(0);
}

/* -------------------------------------------------------------------------------------------- */
__inline DWORD dwGetImportedFunctionEntryFromImageBase(DWORD dwImageBase,LPCSTR lpProcName)/**/
{
	char *lpBuffer=(char*) dwImageBase;
	PIMAGE_OPTIONAL_HEADER pPEOptionalHeader=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(lpBuffer);
	DWORD ImportTableRVA=pPEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
	if (ImportTableRVA)
	{
		PIMAGE_IMPORT_MODULE_DIRECTORY pid=(PIMAGE_IMPORT_MODULE_DIRECTORY) &lpBuffer[ImportTableRVA];
    return(dwInternalGetImportedFunctionEntry(dwImageBase,pid,lpProcName));
  }
  return(0);
}

/* -------------------------------------------------------------------------------------------- */
__inline
DWORD dwGetInternalExportedFunctionEntry(DWORD dwImageBase,PIMAGE_EXPORT_DIRECTORY ped,LPCSTR lpProcName)/**/
{
	char *lpBuffer=(char*) dwImageBase;
  if ( (lpBuffer) && (ped) )
  {
    DWORD *FunctionNamePtr=(DWORD*) &lpBuffer[(DWORD)ped->AddressOfNames];
    DWORD *FunctionAdressPtr=(DWORD*) &lpBuffer[(DWORD)ped->AddressOfFunctions];
    WORD *FunctionOrdinalPtr=(WORD*) &lpBuffer[(DWORD)ped->AddressOfNameOrdinals];
    int i;
    for (i=0; i<(int)ped->NumberOfNames; i++)
    {
      char *NamePtr=(char*) &lpBuffer[*FunctionNamePtr];
			DWORD AddrPtr=*(FunctionAdressPtr + *FunctionOrdinalPtr);
      //if (!StringCompare(NamePtr,lpProcName))
	  if (!StringCompareToCryptKey(NamePtr,lpProcName))
      {
        return(AddrPtr);
      }
      FunctionNamePtr++;
      FunctionOrdinalPtr++;
    }
	}
	return(0);
}

/* -------------------------------------------------------------------------------------------- */
__inline DWORD dwGetExportedFunctionEntryFromImageBase(DWORD dwImageBase,LPCSTR lpProcName)/**/
{
	char *lpBuffer=(char*) dwImageBase;
	PIMAGE_OPTIONAL_HEADER pPEOptionalHeader=(PIMAGE_OPTIONAL_HEADER) OPTHDROFFSET(lpBuffer);
	DWORD ExportTableRVA=pPEOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
	if (ExportTableRVA)
	{
		PIMAGE_EXPORT_DIRECTORY ped=(PIMAGE_EXPORT_DIRECTORY) &lpBuffer[ExportTableRVA];
    return(dwGetInternalExportedFunctionEntry(dwImageBase,ped,lpProcName));
	}
	return(0);
}

/* -------------------------------------------------------------------------------------------- */
#if defined(__cplusplus)
}
#endif

/* -------------------------------------------------------------------------------------------- */
#endif /* __PEINLINE_H__ } */

