//					EXPORTS.CPP

#include <windows.h>

#include "exports.h"
#include "pefiles.h"
#include "xref.h"
#include "disasm.h"
#include "dasm.h"
#include "textout.h"
#include "opcodes.h"

exp::exp(void)
{ explist=NULL;
  onames=NULL;
}

exp::~exp(void)
{ struct exportlist *nxt;
  struct ordnames *nxto;
  while(explist)
  { nxt=explist->next;
	 delete explist->name;
	 delete explist;
	 explist=nxt;
  }
  while(onames)
  { nxto=onames->next;
	 delete onames;
	 onames=nxto;
  }
}

void exp::summary(void)
{ struct codedata *exporttable,*idata;
  struct exportdirentry *expdir;
  unsigned long exportrva,datarva,*fnaddr,*nnaddr,adr,ef,en,eo;
  unsigned short int *onaddr;
  unsigned char *expname;
  unsigned char *chktable;
  unsigned long image_base;
  unsigned long numsymbols;
  unsigned long i;
  exporttable=pe_exe.getexports();
  if(exporttable==NULL)return;
  image_base=pe_exe.getimagebase();
  exportrva=exporttable->addr-image_base;
  adr=exporttable->addr;
  disassemble.hintdata(adr,OP_DD);
  disassemble.hintdata(adr+4,OP_DD);
  disassemble.hintdata(adr+8,OP_DW);
  disassemble.hintdata(adr+10,OP_DW);
  disassemble.hintdata(adr+12,OP_DD);
  disassemble.hintdata(adr+16,OP_DD);
  disassemble.hintdata(adr+20,OP_DD);
  disassemble.hintdata(adr+24,OP_DD);
  disassemble.hintdata(adr+28,OP_DD);
  expdir=(struct exportdirentry *)exporttable->dataptr;
  PrintBuff("");
  PrintBuff("Export Summary");
  PrintBuff("==============");
  if((expdir->namerva<exportrva)||(expdir->namerva>exportrva+exporttable->size))
  { idata=pe_exe.getinitdata();
	 while(idata!=NULL)
	 { datarva=idata->addr-image_base;
		if((expdir->namerva>=datarva)&&(expdir->namerva<datarva+idata->size))break;
		idata=idata->next;
	 }
	 if(idata==NULL)
	 { idata=pe_exe.getcode();
		while(idata!=NULL)
		{ datarva=idata->addr-image_base;
		  if((expdir->namerva>=datarva)&&(expdir->namerva<datarva+idata->size))break;
		  idata=idata->next;
		}
	 }
	 if(idata!=NULL)
	 { expname=expdir->namerva-datarva+idata->dataptr;
	 }
  }
  else
  { expname=expdir->namerva-exportrva+exporttable->dataptr;
  }
  disassemble.hintdata(expdir->namerva+image_base,OP_DS);
  PrintBuff("Export : %s",expname);
  numsymbols=expdir->numfunctions;
  chktable=new unsigned char [numsymbols];
  for(i=0;i<numsymbols;i++)chktable[i]=0;
  if(expdir->numnames<numsymbols)numsymbols=expdir->numnames;
  if((expdir->nameaddrrva<exportrva)||(expdir->nameaddrrva>exportrva+exporttable->size))
  { idata=pe_exe.getinitdata();
	 while(idata!=NULL)
	 { datarva=idata->addr-image_base;
		if((expdir->nameaddrrva>=datarva)&&(expdir->nameaddrrva<datarva+idata->size))break;
		idata=idata->next;
	 }
	 if(idata==NULL)
	 { idata=pe_exe.getcode();
		while(idata!=NULL)
		{ datarva=idata->addr-image_base;
		  if((expdir->nameaddrrva>=datarva)&&(expdir->nameaddrrva<datarva+idata->size))break;
		  idata=idata->next;
		}
	 }
	 if(idata!=NULL)
	 { nnaddr=(unsigned long *)(idata->dataptr+expdir->nameaddrrva-idata->addr+image_base);
	 }
  }
  else
  { nnaddr=(unsigned long *)(exporttable->dataptr+expdir->nameaddrrva-exporttable->addr+image_base);
	 idata=exporttable;
  }
  fnaddr=(unsigned long *)pe_exe.findrva(expdir->funcaddrrva);
  onaddr=(unsigned short *)pe_exe.findrva(expdir->ordsaddrrva);
  ef=expdir->funcaddrrva+image_base;
  eo=expdir->ordsaddrrva+image_base;
  en=expdir->nameaddrrva+image_base;
  while(numsymbols)
  { disassemble.hintdata(ef,OP_DD);
	 disassemble.hintdata(eo,OP_DW);
	 disassemble.hintdata(en,OP_DD);
	 PrintBuff("  %lx %4lx ",fnaddr[onaddr[0]]+image_base,onaddr[0]+1);
	 chktable[onaddr[0]]=1;
	 LastPrintBuffEpos(15);
	 addtoexplist(idata->dataptr+(*nnaddr)-idata->addr+image_base,image_base+fnaddr[onaddr[0]]);
	 disassemble.hintdata((*nnaddr)+image_base,OP_DS);
	 numsymbols--;
	 onaddr++;
	 nnaddr++;
	 ef+=4;
	 eo+=2;
	 en+=4;
  }
  if(expdir->numfunctions>expdir->numnames)
  { PrintBuff("");
	 PrintBuff("Export by Ordinal");
	 PrintBuff("=================");
	 for(i=0;i<expdir->numfunctions;i++)
	 { if(!chktable[i])
		{ PrintBuff("  %lx %4lx ",fnaddr[i]+image_base,i+1);
		  LastPrintBuffEpos(15);
		  addtoexplist(newexpname(i+1),fnaddr[i]+image_base);
		  if(!fnaddr[i])LastPrintBuff(" Zero (No function)");
		}
	 }
  }
  PrintBuff("");
  delete chktable;
}

void exp::addtoexplist(unsigned char *name,unsigned long addr)
{ struct exportlist *addit,*prev,*newone;
  unsigned char *newname,buff[256],buff2[256];
  unsigned int namelen,i,j,k,atcount,bpoint;
  BOOL brac,pointer,rpointer;
  prev=NULL;
  if(explist==NULL)
  { explist=new struct exportlist;
	 addit=explist;
	 addit->next=NULL;
  }
  else
  { addit=explist;
	 while((addr>addit->addr)&&(addit->next!=NULL))
	 { prev=addit;
		addit=addit->next;
	 }
	 if(addr>addit->addr)
	 { addit->next=new struct exportlist;
		addit=addit->next;
		addit->next=NULL;
	 }
	 else
	 { newone=new struct exportlist;
		newone->next=addit;
		addit=newone;
		if(prev!=NULL)prev->next=newone;
		else explist=newone;
	 }
  }
  addit->addr=addr;
  atcount=0;
  i=0;
  j=0;
  brac=FALSE;
  while(name[i])
  { if(name[i]=='@')
	 { atcount++;
		if(atcount>1)
		{ buff[j++]=':';
		  buff[j++]=':';
		}
	 }
	 else if((name[i]=='$')&&(name[i+1]=='q')&&(!brac))
	 { brac=TRUE;
		bpoint=j;
		buff[j++]='(';
		i+=1;
	 }
	 else if((name[i]=='$')&&(name[i+1]=='x')&&(name[i+2]=='q')&&(!brac))
	 { brac=TRUE;
		bpoint=j;
		buff[j++]='(';
		i+=2;
	 }
	 else if(!strnicmp((char *)&name[i],"$bctr",5))
	 { k=0;
		while((buff[k]!=':')&&(k<20))
		{ buff[j++]=buff[k++];
		}
		i+=4;
	 }
	 else if(!strnicmp((char *)&name[i],"$bdtr",5))
	 { k=0;
		buff[j++]='~';
		while((buff[k]!=':')&&(k<20))
		{ buff[j++]=buff[k++];
		}
		i+=4;
	 }
	 else if(!strnicmp((char *)&name[i],"$bdla",5))
	 { strcpy((char *)&buff[j],"delete");
		j+=6;
		i+=4;
	 }
	 else if(!strnicmp((char *)&name[i],"$bnwa",5))
	 { strcpy((char *)&buff[j],"new");
		j+=3;
		i+=4;
	 }
	 else if(!strnicmp((char *)&name[i],"$bdele",6))
	 { strcpy((char *)&buff[j],"delete");
		j+=6;
		i+=5;
	 }
	 else if(!strnicmp((char *)&name[i],"$bnew",5))
	 { strcpy((char *)&buff[j],"new");
		j+=5;
		i+=4;
	 }
	 else buff[j++]=name[i];
	 i++;
  }
  if(brac)buff[j++]=')';
  buff[j]=0;
  strcpy((char *)buff2,(char *)buff);
  if(brac)
  { j=bpoint;
	 k=bpoint;
	 i=0;
	 pointer=FALSE;
	 rpointer=FALSE;
	 while(buff[j])
	 { if((buff[j]=='p')&&(!i))
		{ pointer=TRUE;
		  j++;
		}
		if((buff[j]=='r')&&(!i))
		{ rpointer=TRUE;
		  j++;
		}
		else if((buff[j]=='i')&&(!i))
		{ i=1;
		  strcpy((char *)&buff2[k],"int");
		  k+=3;
		  j+=1;
		}
		else if((buff[j]=='c')&&(!i))
		{ i=1;
		  strcpy((char *)&buff2[k],"char");
		  k+=4;
		  j+=1;
		}
		else if((buff[j]=='v')&&(!i))
		{ i=1;
		  strcpy((char *)&buff2[k],"void");
		  k+=4;
		  j+=1;
		}
		else if((buff[j]=='l')&&(!i))
		{ i=1;
		  strcpy((char *)&buff2[k],"long");
		  k+=4;
		  j+=1;
		}
		else if((buff[j]=='u')&&(buff[j+1]=='i')&&(!i))
		{ i=1;
		  strcpy((char *)&buff2[k],"uint");
		  k+=4;
		  j+=2;
		}
		else if((buff[j]==':')&&(buff[j+1]==':')&&(i))
		{ strcpy((char *)&buff2[k],"::");
		  k+=2;
		  j+=2;
		}
		else if((buff[j]=='t')&&((buff[j+1]>='0')&&(buff[j+1]<='9'))&&(!i))
		{ buff2[k++]=buff[j++];
		  buff2[k++]=buff[j++];
		  i=1;
		}
		else if(((buff[j]>='0')&&(buff[j]<='9'))&&(!i))
		{ i=buff[j]-'0';
		  j++;
		  if((buff[j]>='0')&&(buff[j]<='9'))
		  { i=i*10+buff[j]-'0';
			 j++;
		  }
		  i++;
		}
		else buff2[k++]=buff[j++];
		if(i)
		{ i--;
		  if(!i)
		  { if((pointer)&&(buff2[k-1]!=')'))buff2[k++]='*';
			 if((rpointer)&&(buff2[k-1]!=')'))buff2[k++]='&';
			 if((buff[j]!=')')&&(buff2[k-1]!=')'))
				buff2[k++]=',';
			 pointer=FALSE;
          rpointer=FALSE;
		  }
		}
	 }
	 buff2[k]=0;
  }
  namelen=strlen((char *)buff2);
  newname=new unsigned char[namelen+1];
  strcpy((char *)newname,(char *)buff2);
  addit->name=newname;
  LastPrintBuff("%s",newname);
  xr.addxref(addr,0,XREF_EXPORT);
}

BOOL exp::isexport(unsigned long address)
{ struct exportlist *ilist;
  ilist=explist;
  while(ilist!=NULL)
  { if(address==ilist->addr)return TRUE;
	 ilist=ilist->next;
  }
  return FALSE;
}

void exp::printname(unsigned long address)
{ struct exportlist *ilist;
  BOOL pone=FALSE;
  ilist=explist;
  while(ilist!=NULL)
  { if(address==ilist->addr)
	 { if(pone) LastPrintBuff(",");
		LastPrintBuff("%s ",ilist->name);
		pone=TRUE;
	 }
	 ilist=ilist->next;
  }
}

unsigned char *exp::newexpname(unsigned long i)
{ char buff[256];
  struct ordnames *on;
  wsprintf(buff,"Export::Ord%04lx",i);
  if(onames==NULL)
  { onames=new struct ordnames;
	 onames->next=NULL;
	 strcpy(onames->name,buff);
	 on=onames;
  }
  else
  { on=onames;
	 while(on->next!=NULL)on=on->next;
	 on->next=new struct ordnames;
	 on=on->next;
	 on->next=NULL;
	 strcpy(on->name,buff);
  }
  return on->name;
}