//					RESOURCE.CPP

#include <windows.h>
#include <winver.h>

#include "resource.h"
#include "textout.h"
#include "pefiles.h"
#include "dasm.h"

#define GRAYED         0x0001     // 'GRAYED' keyword
#define INACTIVE       0x0002     // 'INACTIVE' keyword
#define BITMAP         0x0004     // 'BITMAP' keyword
#define OWNERDRAW      0x0100     // 'OWNERDRAW' keyword
#define CHECKED        0x0008     // 'CHECKED' keyword
#define POPUP          0x0010     // Used internally
#define MENUBARBREAK   0x0020     // 'MENUBARBREAK' keyword
#define MENUBREAK      0x0040     // 'MENUBREAK' keyword
#define ENDMENU        0x0080     // Used internally

#define BUTTON     0x80
#define EDIT       0x81
#define STATIC     0x82
#define LISTBOX    0x83
#define SCROLLBAR  0x84
#define COMBOBOX   0x85

res::res(void)
{
}

res::~res(void)
{
}

void res::summary(void)
{ struct codedata *resourcetable;
  resourcetable=pe_exe.getresources();
  if(resourcetable==NULL)return;
  PrintBuff("Resources Summary");
  PrintBuff("=================");
  rawdata=resourcetable->dataptr;
  dirsummary(rawdata);
  PrintBuff("");
}

void res::dirsummary(unsigned char *dta)
{ struct restable *resdir;
  struct restableentry *rentry;
  unsigned char *name;
  char nbuff[100];
  int clen;
  unsigned long numitems;
  resdir=(struct restable *)dta;
  numitems=resdir->numnames+resdir->numids;
  rentry=(struct restableentry *)(resdir+1);
  while(numitems)
  { PrintBuff("");
	 if(rentry->id&0x80000000)
	 { name=rawdata+((rentry->id)&0x7fffffff);
		clen=((short int *)name)[0];
		WideCharToMultiByte(CP_ACP,0,(const wchar_t *)(name+2),clen,nbuff,100,NULL,NULL);
		nbuff[clen]=0;
		PrintBuff(" Name : %s",nbuff);
	 }
	 else
	 { PrintBuff(" ");
		currid=rentry->id;
		switch(rentry->id)
		{ case 1:
			 LastPrintBuff("Cursor");
			 break;
		  case 2:
			 LastPrintBuff("Bitmap");
			 break;
		  case 3:
			 LastPrintBuff("Icon");
			 break;
		  case 4:
			 LastPrintBuff("Menu");
			 break;
		  case 5:
			 LastPrintBuff("Dialog");
			 break;
		  case 6:
			 LastPrintBuff("String Table");
			 break;
		  case 7:
			 LastPrintBuff("Font Directory");
			 break;
		  case 8:
			 LastPrintBuff("Font");
			 break;
		  case 9:
			 LastPrintBuff("Accelerators");
			 break;
		  case 10:
			 LastPrintBuff("Unformatted Resource Data");
			 break;
		  case 11:
			 LastPrintBuff("Message Table");
			 break;
		  case 12:
			 LastPrintBuff("Group Cursor");
			 break;
		  case 14:
			 LastPrintBuff("Group Icon");
			 break;
		  case 16:
			 LastPrintBuff("Version Information");
			 break;
		  case 0x2002:
			 LastPrintBuff("New Bitmap");
			 break;
		  case 0x2004:
			 LastPrintBuff("New Menu");
			 break;
		  case 0x2005:
			 LastPrintBuff("New Dialog");
			 break;
		  default:
			 LastPrintBuff("User Defined Id : %02lx",rentry->id);
			 break;
		}
	 }
	 if(rentry->offset&0x80000000) subdirsummary(rawdata+((rentry->offset)&0x7fffffff));
	 else leafnodesummary(rawdata+((rentry->offset)&0x7fffffff));
	 rentry++;
	 numitems--;
  }
}

void res::subdirsummary(unsigned char *dta)
{ struct restable *resdir;
  struct restableentry *rentry;
  unsigned char *name;
  char nbuff[100];
  int clen;
  unsigned long numitems;
  resdir=(struct restable *)dta;
  numitems=resdir->numnames+resdir->numids;
  rentry=(struct restableentry *)(resdir+1);
  while(numitems)
  { if(rentry->id&0x80000000)
	 { name=rawdata+((rentry->id)&0x7fffffff);
		clen=((short int *)name)[0];
		WideCharToMultiByte(CP_ACP,0,(const wchar_t *)(name+2),clen,nbuff,100,NULL,NULL);
		nbuff[clen]=0;
		PrintBuff("   Name : %s",nbuff);
	 }
	 else
	 { PrintBuff("   Id : %02lx ",rentry->id);
		stringid=rentry->id;
	 }
	 if(rentry->offset&0x80000000) leaf2summary(rawdata+((rentry->offset)&0x7fffffff));
	 else leafnodesummary(rawdata+((rentry->offset)&0x7fffffff));
	 rentry++;
	 numitems--;
  }
}

void res::leaf2summary(unsigned char *dta)
{ struct restable *resdir;
  struct restableentry *rentry;
  unsigned long numitems;
  resdir=(struct restable *)dta;
  numitems=resdir->numnames+resdir->numids;
  rentry=(struct restableentry *)(resdir+1);
  while(numitems)
  { leafnodesummary(rawdata+((rentry->offset)&0x7fffffff));
	 rentry++;
	 numitems--;
  }
}

void res::leafnodesummary(unsigned char *dta)
{ struct leafnode *leaf;
  struct codedata *resourcetable;
  unsigned char *iddata;
  unsigned long image_base,vflags;
  int numitems,clen;
  short int flags,pt_size;
  char nbuff[257];
  int popup,popupct;
  struct versioninfo *verinfo;
  struct fixedfileinfo *fixedinfo;
  struct dialogboxheader *hdr;
  struct ctrlheader *ctrl;
  resourcetable=pe_exe.getresources();
  image_base=pe_exe.getimagebase();
  leaf=(struct leafnode *)dta;
  PrintBuff("      Data RVA : %lx",leaf->datarva);
  PrintBuff("      Size     : %lx",leaf->size);
  PrintBuff("      Codepage : %lx",leaf->codepage);
  iddata=rawdata+leaf->datarva-resourcetable->addr+image_base;
  switch(currid)
  { case 4: // menu
		if(((unsigned long *)iddata)[0])
		{ PrintBuff("         ");
		  LastPrintBuff("Unknown Format");
		  break;
		}
		iddata+=4;
		popup=0;
		do
		{ flags=((short int *)iddata)[0];
		  iddata+=2;
		  if (flags&POPUP)
		  { PrintBuff("         ");
			 popup++;
			 popupct=popup;
			 if(popupct>10)popupct=10;
			 while(popupct--)LastPrintBuff("   ");
			 LastPrintBuff("POPUP ");
		  }
		  else
		  { PrintBuff("         ");
			 popupct=popup;
			 if(popupct>10)popupct=10;
			 while(popupct--)LastPrintBuff("   ");
			 LastPrintBuff("%04X  ",((short int *)iddata)[0]);	// ID
			 iddata+=2;
		  }
		  if(((short int *)iddata)[0])
		  { WideCharToMultiByte(CP_ACP,0,(const wchar_t *)(iddata),-1,nbuff,255,NULL,NULL);
			 LastPrintBuffEpos(18);
			 LastPrintBuff("%s",nbuff);
			 iddata+=(strlen(nbuff)+1)*2;
		  }
		  else
		  { iddata+=2;
		  }
		  if(flags&GRAYED)LastPrintBuff(" GRAYED");
		  if(flags&BITMAP)LastPrintBuff(" BITMAP");
		  if(flags&OWNERDRAW)LastPrintBuff(" OWNERDRAW");
		  if(flags&CHECKED)LastPrintBuff(" CHECKED");
		  if(flags&MENUBARBREAK)LastPrintBuff(" MENUBARBREAK");
		  if(flags&MENUBREAK)LastPrintBuff(" MENUBREAK");
		  if(popup&&(flags&ENDMENU))
		  { flags=0;
			 popup--;
		  }
		  if (flags & ENDMENU)
		  { LastPrintBuff("   ENDMENU");
		  }
		} while(!(flags&ENDMENU));
		PrintBuff("");
		break;
	 case 5: // dialog
		hdr=(struct dialogboxheader *)iddata;
		if(hdr->style)
		{ vflags=hdr->style;
		  PrintBuff("         Style  :");
		  if(vflags&DS_ABSALIGN) LastPrintBuff(" DS_ABSALIGN");
		  if(vflags&DS_SYSMODAL) LastPrintBuff(" DS_SYSMODAL");
		  if(vflags&DS_LOCALEDIT) LastPrintBuff(" DS_LOCALEDIT");
		  if(vflags&DS_SETFONT) LastPrintBuff(" DS_SETFONT");
		  if(vflags&DS_MODALFRAME) LastPrintBuff(" DS_MODALFRAME");
		  if(vflags&DS_NOIDLEMSG) LastPrintBuff(" DS_NOIDLEMSG");
		  if(vflags&DS_SETFOREGROUND) LastPrintBuff(" DS_SETFOREGROUND");
		  if(vflags&WS_BORDER) LastPrintBuff(" WS_BORDER");
		  if(vflags&WS_CAPTION) LastPrintBuff(" WS_CAPTION");
		  if(vflags&WS_CHILD) LastPrintBuff(" WS_CHILD");
		  if(vflags&WS_CLIPCHILDREN) LastPrintBuff(" WS_CLIPCHILDREN");
		  if(vflags&WS_CLIPSIBLINGS) LastPrintBuff(" WS_CLIPSIBLINGS");
		  if(vflags&WS_DISABLED) LastPrintBuff(" WS_DISABLED");
		  if(vflags&WS_DLGFRAME) LastPrintBuff(" WS_DLGFRAME");
		  if(vflags&WS_GROUP) LastPrintBuff(" WS_GROUP");
		  if(vflags&WS_HSCROLL) LastPrintBuff(" WS_HSCROLL");
		  if(vflags&WS_MAXIMIZE) LastPrintBuff(" WS_MAXIMIZE");
		  if(vflags&WS_MAXIMIZEBOX) LastPrintBuff(" WS_MAXIMIZEBOX");
		  if(vflags&WS_MINIMIZE) LastPrintBuff(" WS_MINIMIZE");
		  if(vflags&WS_MINIMIZEBOX) LastPrintBuff(" WS_MINIMIZEBOX");
		  if(vflags&WS_OVERLAPPED) LastPrintBuff(" WS_OVERLAPPED");
		  if(vflags&WS_POPUP) LastPrintBuff(" WS_POPUP");
		  if(vflags&WS_SIZEBOX) LastPrintBuff(" WS_SIZEBOX");
		  if(vflags&WS_SYSMENU) LastPrintBuff(" WS_SYSMENU");
		  if(vflags&WS_TABSTOP) LastPrintBuff(" WS_TABSTOP");
		  if(vflags&WS_THICKFRAME) LastPrintBuff(" WS_THICKFRAME");
		  if(vflags&WS_VISIBLE) LastPrintBuff(" WS_VISIBLE");
		  if(vflags&WS_VSCROLL) LastPrintBuff(" WS_VSCROLL");
		}
		PrintBuff("         (x,y)  : %02X,%02X",hdr->x,hdr->y);
		PrintBuff("         (cx,cy): %02X,%02X",hdr->cx,hdr->cy);
		iddata+=sizeof(struct dialogboxheader);
		PrintBuff("         Menu   :");
		iddata+=print_name_or_ord(iddata,0,0);
		PrintBuff("         Class  :");
		iddata+=print_name_or_ord(iddata,0,0);
		PrintBuff("         Caption:");
		if(((short int *)iddata)[0])
		{ WideCharToMultiByte(CP_ACP,0,(const wchar_t *)(iddata),-1,nbuff,255,NULL,NULL);
		  LastPrintBuffEpos(18);
		  LastPrintBuff("%s",nbuff);
		  iddata+=(strlen(nbuff)+1)*2;
		}
		else
		{ iddata+=2;
		}
		PrintBuff("         Items  : %02X",hdr->numberofitems);
		if (hdr->style&DS_SETFONT)
		{ pt_size=((unsigned short *)iddata)[0];  // skip past pt. size
		  iddata+=2;
		  PrintBuff("         Font   :");
		  if(((short int *)iddata)[0])
		  { WideCharToMultiByte(CP_ACP,0,(const wchar_t *)(iddata),-1,nbuff,255,NULL,NULL);
			 LastPrintBuffEpos(18);
			 LastPrintBuff("%s",nbuff);
			 iddata+=(strlen(nbuff)+1)*2;
		  }
		  else
		  { iddata+=2;
		  }
		  LastPrintBuff("(%u Pt.)", pt_size);
		}
		// now at end of header; do each control
	  /*	for(numitems=0;numitems<hdr->numberofitems;numitems++)
		{ while(((unsigned long)(iddata-(unsigned char *)hdr))&3)iddata++;	// make DWORD-aligned!
		  ctrl=(struct ctrlheader *) iddata;
		  PrintBuff("         %04X ",ctrl->wid);
		  LastPrintBuff("(%02X,%02X,%02X,%02X) ",ctrl->x,ctrl->y,ctrl->cx,ctrl->cy);
		  iddata+=sizeof(struct ctrlheader);
		  iddata+=print_name_or_ord(iddata,1,ctrl->style);
		  PrintBuff("            ");
		  iddata+=print_name_or_ord(iddata,0,0);
		  iddata+=2;	// skip nExtraStuff
		}*/
		break;
	 case 6: // string table
		numitems=16;
		while(numitems>0)
		{ clen=((short int *)iddata)[0];
		  if(clen)
		  { WideCharToMultiByte(CP_ACP,0,(const wchar_t *)(iddata+2),clen,nbuff,255,NULL,NULL);
			 if(clen>255)clen=clen&255;
			 nbuff[clen]=0;
			 PrintBuff("");
			 LastPrintBuffEpos(10);
			 LastPrintBuff("%02X %s",(stringid-1)*16+16-numitems,nbuff);
			 iddata+=(((short int *)iddata)[0]+1)*2;
		  }
		  else
		  { iddata+=2;
		  }
		  numitems--;
		}
		PrintBuff("");
		break;
	 case 16:  // version info
		verinfo=(struct versioninfo *)iddata;
		PrintBuff("          Type   : %X",verinfo->type);
		iddata+=6;
		clen=((short int *)iddata)[0];
		if(clen)
		{ WideCharToMultiByte(CP_ACP,0,(const wchar_t *)(iddata+2),-1,nbuff,255,NULL,NULL);
		  PrintBuff("");
		  LastPrintBuffEpos(10);
		  LastPrintBuff("%s",nbuff);
		  iddata+=(strlen(nbuff)+1)*2;
		}
		else
		{ iddata+=2;
		}
		iddata+=4;
		fixedinfo=(struct fixedfileinfo *)iddata;
		if(fixedinfo->signature!=0xfeef04bd)
		{ PrintBuff("          Bad Signature:%02x",fixedinfo->signature);
		  break;
		}
		PrintBuff("          File Version    : %02d.%02d.%02d.%02d",HIWORD(fixedinfo->fileversionms),
		  LOWORD(fixedinfo->fileversionms),HIWORD(fixedinfo->fileversionms),LOWORD(fixedinfo->fileversionms));
		PrintBuff("          Product Version : %02d.%02d.%02d.%02d",HIWORD(fixedinfo->productversionms),
		  LOWORD(fixedinfo->productversionms),HIWORD(fixedinfo->productversionls),LOWORD(fixedinfo->productversionls));
		vflags=fixedinfo->fileflags & fixedinfo->fileflagmask;
		PrintBuff("          Flags           : ");
		if(!vflags) LastPrintBuff("(none)");
		if(vflags&VS_FF_DEBUG)        LastPrintBuff("Debug ");
		if(vflags&VS_FF_PRERELEASE)   LastPrintBuff("Prerelease ");
		if(vflags&VS_FF_PATCHED)	     LastPrintBuff("Patched ");
		if(vflags&VS_FF_PRIVATEBUILD) LastPrintBuff("PrivateBuild ");
		if(vflags&VS_FF_INFOINFERRED) LastPrintBuff("InfoInferred ");
		if(vflags&VS_FF_SPECIALBUILD) LastPrintBuff("SpecialBuild ");
		PrintBuff("          File OS         : ");
		switch(LOWORD(fixedinfo->fileos))
		{ case VOS__WINDOWS16:
			 LastPrintBuff("16-Bit Windows");
			 break;
		  case VOS__PM16:
			 LastPrintBuff("16-Bit Presentation Manager");
			 break;
		  case VOS__PM32:
			 LastPrintBuff("32-Bit Presentation Manager");
			 break;
		  case VOS__WINDOWS32:
			 LastPrintBuff("Win32");
			 break;
		  default:
			 LastPrintBuff("(unknown)");
			 break;
		}
		LastPrintBuff(" on ");
		switch(fixedinfo->fileos&0xffff0000)
		{ case VOS_DOS:
			 LastPrintBuff("MS-DOS");
			 break;
		  case VOS_OS216:
			 LastPrintBuff("16-Bit OS/2");
			 break;
		  case VOS_OS232:
			 LastPrintBuff("32-Bit OS/2");
			 break;
		  case VOS_NT:
			 LastPrintBuff("NT");
			 break;
		  default:
			 LastPrintBuff("(unknown)");
			 break;
		}
		PrintBuff("          Type            : ");
		switch(fixedinfo->filetype)
		{ case VFT_APP:
			 LastPrintBuff("Exe");
			 break;
		  case VFT_DLL:
			 LastPrintBuff("DLL");
			 break;
		  case VFT_DRV:
			 switch(fixedinfo->filesubtype)
			 { case VFT2_DRV_COMM:
				  LastPrintBuff("Driver (serial)");
				  break;
				case VFT2_DRV_PRINTER:
				  LastPrintBuff("Driver (Printer)");
				  break;
				case VFT2_DRV_KEYBOARD:
				  LastPrintBuff("Driver (Keyboard)");
				  break;
				case VFT2_DRV_LANGUAGE:
				  LastPrintBuff("Driver (Language)");
				  break;
				case VFT2_DRV_DISPLAY:
				  LastPrintBuff("Driver (Display)");
				  break;
				case VFT2_DRV_MOUSE:
				  LastPrintBuff("Driver (Mouse)");
				  break;
				case VFT2_DRV_NETWORK:
				  LastPrintBuff("Driver (Network)");
				  break;
				case VFT2_DRV_SYSTEM:
				  LastPrintBuff("Driver (System)");
				  break;
				case VFT2_DRV_INSTALLABLE:
				  LastPrintBuff("Driver (installable)");
				  break;
				case VFT2_DRV_SOUND:
				  LastPrintBuff("Driver (Sound)");
				  break;
				case VFT2_DRV_INPUTMETHOD:
				  LastPrintBuff("Input Method");
				  break;
				case VFT2_UNKNOWN:
				default:
				  LastPrintBuff("Driver (unknown)");
				  break;
			 }
			 break;
		  case VFT_FONT:
			 switch(fixedinfo->filesubtype)
			 { case VFT2_FONT_RASTER:
				  LastPrintBuff("Font (Raster)");
				  break;
				case VFT2_FONT_VECTOR:
				  LastPrintBuff("Font (Vector)");
				  break;
				case VFT2_FONT_TRUETYPE:
				  LastPrintBuff("Font (TrueType)");
				  break;
				case VFT2_UNKNOWN:
				default:
				  LastPrintBuff("Font (unknown)");
				  break;
			 }
			 break;
		  case VFT_VXD:
			 LastPrintBuff("VxD, device id == %ld",fixedinfo->filesubtype);
			 break;
		  case VFT_STATIC_LIB:
			 LastPrintBuff("Static Lib");
			 break;
		  case VFT_UNKNOWN:
		  default:
			 LastPrintBuff("(unknown)");
			 break;
		}
		break;
	 default:
		break;
  }
}

void res::print_edit(unsigned long style)
{ if(style && (ES_LEFT | WS_BORDER | WS_TABSTOP))
	 LastPrintBuff("EDITTEXT ");
  else
  { LastPrintBuff("EDIT ( ");
	 if(style&ES_LEFT) LastPrintBuff("ES_LEFT ");
	 if(style&ES_CENTER) LastPrintBuff("ES_CENTER ");
	 if(style&ES_RIGHT) LastPrintBuff("ES_RIGHT ");
	 if(style&ES_MULTILINE) LastPrintBuff("ES_MULTILINE ");
	 if(style&ES_UPPERCASE) LastPrintBuff("ES_UPPERCASE ");
	 if(style&ES_LOWERCASE) LastPrintBuff("ES_LOWERCASE ");
	 if(style&ES_PASSWORD) LastPrintBuff("ES_PASSWORD ");
	 if(style&ES_AUTOVSCROLL) LastPrintBuff("ES_AUTOVSCROLL ");
	 if(style&ES_AUTOHSCROLL) LastPrintBuff("ES_AUTOHSCROLL ");
	 if(style&ES_NOHIDESEL) LastPrintBuff("ES_NOHIDESEL ");
	 if(style&ES_OEMCONVERT) LastPrintBuff("ES_OEMCONVERT ");
	 if(style&ES_READONLY) LastPrintBuff("ES_READONLY ");
	 if(style&ES_WANTRETURN) LastPrintBuff("ES_WANTRETURN ");
	 LastPrintBuff(")");
  }
}

void res::print_button(unsigned long style)
{ LastPrintBuff("BUTTON ");
  if(style&BS_CHECKBOX) LastPrintBuff("BS_CHECKBOX ");
  if(style&BS_PUSHBUTTON) LastPrintBuff("BS_PUSHBUTTON ");
  if(style&BS_GROUPBOX) LastPrintBuff("BS_GROUPBOX ");
  if(style&BS_DEFPUSHBUTTON) LastPrintBuff("BS_DEFPUSHBUTTON ");
  if(style&BS_RADIOBUTTON) LastPrintBuff("BS_RADIOBUTTON ");
  if(style&BS_AUTOCHECKBOX) LastPrintBuff("BS_AUTOCHECKBOX ");
  if(style&BS_AUTO3STATE) LastPrintBuff("BS_AUTO3STATE ");
  if(style&BS_AUTORADIOBUTTON) LastPrintBuff("BS_AUTORADIOBUTTON ");
  if(style&BS_3STATE) LastPrintBuff("BS_3STATE ");
}

void res::print_static(unsigned long style)
{ if(style&SS_LEFT) LastPrintBuff("SS_LEFT ");
  else if(style&SS_RIGHT) LastPrintBuff("SS_RIGHT ");
  else if(style&SS_CENTER) LastPrintBuff("SS_CENTER ");
  else if(style&SS_ICON) LastPrintBuff("SS_ICON ");
  else LastPrintBuff("STATIC ");  // others not interesting??
}

void res::print_listbox(unsigned long style)
{ if(style & (WS_BORDER | LBS_NOTIFY))
	 LastPrintBuff("LISTBOX ");
  else
	 LastPrintBuff("LISTBOX (%08lX) ", style);
}

void res::print_scrollbar(unsigned long style)
{ LastPrintBuff("SCROLLBAR (%08lX) ", style);
}

void res::print_combobox(unsigned long style)
{ LastPrintBuff("COMBOBOX (%08lX) ", style);
}

unsigned short res::print_name_or_ord(unsigned char *idata,BOOL do_control,unsigned long style)
{ unsigned short *data=(unsigned short *)idata;
  char nbuff[100];
  if(*data==0xFFFF)
  { if(do_control)
	 { switch (data[1])
		{ case BUTTON:
			 print_button(style);
			 break;
		  case EDIT:
			 print_edit(style);
			 break;
		  case STATIC:
			 print_static(style);
			 break;
		  case LISTBOX:
			 print_listbox(style);
			 break;
		  case SCROLLBAR:
			 print_scrollbar(style);
			 break;
		  case COMBOBOX:
			 print_combobox(style);
			 break;
		  default:
			 PrintBuff("         %04X (Style %08lX)",data[1],style);
			 break;
		}
	 }
	 else PrintBuff("         %04X", data[1]);
	 return 4;
  }
  else
  { if(((short int *)idata)[0])
	 { WideCharToMultiByte(CP_ACP,0,(const wchar_t *)(idata),-1,nbuff,255,NULL,NULL);
		LastPrintBuffEpos(18);
		LastPrintBuff("%s",nbuff);
		return (strlen(nbuff)+1)*2;
	 }
  }
  return 2;
}


