//
// OllyDbg ASM To HTML Converter v2.1
//
// Crick - 2001
//-----------------------------------
/*header: oa2hres.h
  resources: oa2h.rc
/*<---------------------------------->*/
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <string.h>
#include "oa2hres.h"

#define MAXBUFF 256

typedef unsigned long ulong;

/* prototype for the dialog box function. */
static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
/*
Win main just registers a class of the same type that the dialog class, and
then calls DialogBox. Then it exits. The return value is the return value of
the dialog procedure.
*/

HICON hIcon;
OPENFILENAME ofn;
FILE *inf, *outf;
char path[MAXBUFF], patho[MAXBUFF], nfile[MAXBUFF];

char vhtmlfont[MAXBUFF]="Courier New", vhtmlcolor[MAXBUFF]="#008000", vbackground[MAXBUFF]="#FFFFFF", vfontsize[MAXBUFF]="x-small";
char *htmlfont=vhtmlfont, *htmlcolor=vhtmlcolor, *background=vbackground, *fontsize=vfontsize;
char vcellpadd[3]="0", vtable[2]="0", vwidth[12]=">", vcellspac[3]="0";
char *cellpadd=vcellpadd, *table=vtable, *width=vwidth, *cellspac=vcellspac;

int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nCmdShow)
{
	WNDCLASS wc;

	memset(&wc,0,sizeof(wc));
	wc.lpfnWndProc = DefDlgProc;
	wc.cbWndExtra = DLGWINDOWEXTRA;
	wc.hInstance = hinst;
	wc.hIcon = LoadIcon(hinst,MAKEINTRESOURCE(IDICON200));
	hIcon = wc.hIcon;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
	wc.lpszClassName = "oa2h";
	RegisterClass(&wc);

	return DialogBox(hinst, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, (DLGPROC) DialogFunc);

}

static int InitializeApp(HWND hDlg,WPARAM wParam, LPARAM lParam)
{
	SendMessage(hDlg,WM_SETICON,ICON_SMALL,(LPARAM) hIcon);
	SendDlgItemMessage(hDlg,IDSIZE,CB_ADDSTRING,0,(LPARAM) "xx-small");
	SendDlgItemMessage(hDlg,IDSIZE,CB_ADDSTRING,0,(LPARAM) "x-small");
	SendDlgItemMessage(hDlg,IDSIZE,CB_ADDSTRING,0,(LPARAM) "small");
	SendDlgItemMessage(hDlg,IDSIZE,CB_ADDSTRING,0,(LPARAM) "medium");
	SendDlgItemMessage(hDlg,IDSIZE,CB_ADDSTRING,0,(LPARAM) "large");
	SendDlgItemMessage(hDlg,IDSIZE,CB_ADDSTRING,0,(LPARAM) "x-large");
	SendDlgItemMessage(hDlg,IDSIZE,CB_ADDSTRING,0,(LPARAM) "xx-large");
	SendDlgItemMessage(hDlg,IDSIZE,CB_SETCURSEL,0,0);
	SetDlgItemText(hDlg,IDFONT,htmlfont);
	SetDlgItemText(hDlg,IDCOLOR,htmlcolor);
	SetDlgItemText(hDlg,IDBACKG,background);
	SetDlgItemText(hDlg,IDSIZE,fontsize);
	SetDlgItemText(hDlg,IDCELLSPACING,cellspac);
	SetDlgItemText(hDlg,IDCELLPADDING,cellpadd);
	return TRUE;
}

int SelectFileToConvert(HWND hDlg)
{
	ofn.lStructSize = sizeof(ofn);
	ofn.hwndOwner = hDlg;
	ofn.hInstance=GetModuleHandle(NULL);
	ofn.lpstrFile = path;
	ofn.nMaxFile = MAXBUFF;
	ofn.lpstrInitialDir = ".";
	ofn.lpstrFileTitle = nfile;
	ofn.nMaxFileTitle = MAXBUFF;
	ofn.lpstrTitle = "Select File To Convert";
	ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_LONGNAMES;
	return 	GetOpenFileName(&ofn);
}

int SelectaFont(HWND hDlg)
{
	CHOOSEFONT fn;
	static LOGFONT lf;
	BYTE r,g,b;
	strcpy(lf.lfFaceName,htmlfont);
	fn.lStructSize = sizeof(fn);
	fn.hwndOwner = hDlg;
	fn.lpLogFont= &lf;
	fn.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT;
	if (ChooseFont(&fn)) {
		r=GetRValue(fn.rgbColors);
		g=GetGValue(fn.rgbColors);
		b=GetBValue(fn.rgbColors);
		sprintf(htmlcolor,"#%02X%02X%02X",r,g,b);
		strcpy(htmlfont,lf.lfFaceName);
		return TRUE;
	}
	else
		return FALSE;
}

void TrimToken(char *token)
{
	int i=strlen(token)-1, j;
	while ((token[i]==' ' || token[i]=='\n') && i>=0){
		token[i]='\0';
		i--;
	}
	for(j=0;j<=i;j++)
		if (token[j]=='<')
			token[j]='[';
		else
			 if(token[j]=='>')
				 token[j]=']';
}
int Convert(HWND hDlg)
{
	int columns[5];
	int fields, i, j, k;
	char line[MAXBUFF];
	char token[MAXBUFF];

	//Test parameters
	if (htmlfont==NULL){
		MessageBox(hDlg,"The font is invalid!","Font Invalid",MB_OK | MB_ICONERROR);
		return TRUE;
	}
	GetDlgItemText(hDlg,IDCOLOR,htmlcolor,8);
	if (htmlcolor==NULL) {
		MessageBox(hDlg,"The color is invalid!","Color Invalid",MB_OK | MB_ICONERROR);
		return TRUE;
	}
	GetDlgItemText(hDlg,IDBACKG,background,8);
	if (background==NULL) {
		MessageBox(hDlg,"The background color is invalid!","Color Invalid",MB_OK | MB_ICONERROR);
		return TRUE;
	}
	GetDlgItemText(hDlg,IDSIZE,fontsize,10);
	if (fontsize==NULL) {
		MessageBox(hDlg,"The font size is invalid!","Size Invalid",MB_OK | MB_ICONERROR);
		return TRUE;
	}
	GetDlgItemText(hDlg,IDCELLSPACING,cellspac,3);
	if (atoi(cellspac)<0) {
		MessageBox(hDlg,"CellSpacing is invalid!","CellSpacing Invalid",MB_OK | MB_ICONERROR);
		return TRUE;
	}
	GetDlgItemText(hDlg,IDCELLPADDING,cellpadd,3);
	if (atoi(cellpadd)<0) {
		MessageBox(hDlg,"CellPadding is invalid!","CellPadding Invalid",MB_OK | MB_ICONERROR);
		return TRUE;
	}
	// OK! Open files & do conversion.
	if ((inf=fopen(path,"r"))==NULL){
		MessageBox(hDlg,strcat("Can not open file: ",path),"Error Open Input File",MB_OK | MB_ICONERROR);
		return TRUE;
	}
	fgets(line,MAXBUFF,inf);
	if ((fields=sscanf(line,"%u %u %u %u %u",&columns[0],&columns[1],&columns[2],&columns[3],&columns[4]))!=5) {
		MessageBox(hDlg,"The Input File has NO columns header!","Error!",MB_OK | MB_ICONERROR);
		fclose(inf);
		return TRUE;
	}
	for (i=0;i<5;i++)
		columns[i]--;
	strcpy(patho,path);
	if ((outf=fopen(strcat(patho,".htm"),"w"))==NULL){
		MessageBox(hDlg,strcat("Can not open file: ",patho),"Error Open Output File",MB_OK | MB_ICONERROR);
		fclose(inf);
		return TRUE;
	}
	//Write HTML header
	fprintf(outf,"%s","<!-- HTML File generated with OllyDbg ASM To HTML v2.0 (oa2h.exe at http://mrcrick.cjb.net) + Crick-2001 -->\n");
	fprintf(outf,"%s%s%s","<html>\n\t<body bgcolor=",background,">\n");
	fprintf(outf,"%s","\t\t<style> TABLE.column {\n");
	fprintf(outf,"%s%s%s","\t\t\tcolor: ",htmlcolor,";\n");
	fprintf(outf,"%s%s%s","\t\t\tfont-family: ",htmlfont,";\n");
	fprintf(outf,"%s%s%s","\t\t\tfont-size: ",fontsize,";\n");
	fprintf(outf,"%s","\t\t}\n");
	fprintf(outf,"%s","\t\t</style>\n");
	fprintf(outf,"%s%s%s%s%s%s%s","\t\t<table class=column BORDER=",table," CELLSPACING=",cellspac," CELLPADDING=",cellpadd,width);

	//Read input file 'till EOF
	while (fgets(line,MAXBUFF,inf)!=NULL) {
		k=strlen(line);
		if (k<8) continue;
		//New Row
		fprintf(outf,"\n\t\t\t<tr>");
		//Read address field
		for (i=columns[0],j=0;i<columns[1];i++,j++)
			token[j]=line[i];
		token[j]='\0';
		TrimToken(token);
		fprintf(outf,"\n\t\t\t\t<td>%s</td>",token);
		//Read opcodes field
		for (i=columns[2],j=0;i<columns[3];i++,j++)
			token[j]=line[i];
		token[j]='\0';
		TrimToken(token);
		fprintf(outf,"\n\t\t\t\t<td>%s</td>",token);
		//Read mnemonics field
		for (i=columns[3],j=0;i<columns[4];i++,j++)
			token[j]=line[i];
		token[j]='\0';
		TrimToken(token);
		if (k<columns[4]) //If there's no comment, expand column
			fprintf(outf,"\n\t\t\t\t<td colspan=2>%s</td>",token);
		else
			fprintf(outf,"\n\t\t\t\t<td>%s</td>",token);
		//Read comments field if any
		if (k>=columns[4]) {
			for (i=columns[4],j=0;line[i]!='\n';i++,j++)
				token[j]=line[i];
			token[j]='\0';
			TrimToken(token);
			fprintf(outf,"\n\t\t\t\t<td>%s</td>",token);
		}
		fprintf(outf,"\n\t\t\t</tr>");
	}
	//Write HTML foot
	fprintf(outf,"%s","\n\t\t</table>\n\t</body>\n</html>");
	//Close files
	fclose(outf);
	fclose(inf);
	MessageBox(hDlg,"Successfully done :)","Done",MB_OK);
	return TRUE;
}

int About(HWND hDlg)
{
	char *Message;
	Message = "             OllyDbg ASM To HTML Convert\n"
    		  "                               v2.1\n"
			  "                         Crick - 2001\n\n"
			  "Usage:\nFrom OllyDbg, select the Copy->File option\n"
			  "and save the block of disassembled code.\n\n"
			  "Edit this file and add a line with the number\n"
			  "of column in which the field begins.\n"
			  "                (i.e.: 1  9  14  36  77)\n"
			  "(This line MUST be the first line\n"
			  "and MUST contents five numbers)\n\n"
			  "Save the file.\n"
			  "Open with this tool, set options & press Convert\n\n"
			  "Thx to:\n"
			  "Oleh Yuschuk (OllyDbg developer)\n"
			  "http://home.t-online.de/home/Ollydbg\n\n"
			  "Jacob Navia (lcc-win32 developer)\n"
			  "http://www.cs.virginia.edu/~lcc-win32\n\n"
			  "Uri2. For open my eyes with HTML styles.\n"
			  "MrSilver. For his asm2html converter.\n\n"
			  "Plz! bugs and Todo's mailto:crick@wanadoo.es\n"
			  "http://mrcrick.cjb.net";
	MessageBox(hDlg,Message,"About oa2h",MB_OK);
	return TRUE;
}

static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) {
	case WM_INITDIALOG:
		InitializeApp(hwndDlg,wParam,lParam);
		return TRUE;
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
			case IDOK:
				Convert(hwndDlg);
				return TRUE;
			case IDBROWSE:
				if (!SelectFileToConvert(hwndDlg))
					MessageBox(hwndDlg,"You must select a valid input file!","Error",MB_OK | MB_ICONERROR);
				else
					SetDlgItemText(hwndDlg,IDFILE,nfile);
				return TRUE;
			case IDCHOOSSEFONT:
				if (!SelectaFont(hwndDlg))
					MessageBox(hwndDlg,"You must select a valid font!","Error",MB_OK | MB_ICONERROR);
				else {
					SetDlgItemText(hwndDlg,IDFONT,htmlfont);
					SetDlgItemText(hwndDlg,IDCOLOR,htmlcolor);
				}
				return TRUE;
			case IDTABLE:
				if ((strcmp(table,"0")==0))
					table="1";
				else
					table="0";
				return TRUE;
			case IDWIDTH:
				if ((strcmp(width,">")==0))
					width=" WIDTH=100%>";
				else
					width=">";
				return TRUE;
			case IDCANCEL:
				EndDialog(hwndDlg,0);
				return TRUE;
			case IDABOUT:
				About(hwndDlg);
		}
		break;
        /* By default, WM_CLOSE is equivalent to CANCEL */
	case WM_CLOSE:
		EndDialog(hwndDlg,0);
		return TRUE;
	}
	return FALSE;
}
