//
//  PlugIn name: IDA to SoftIce converter (only for 32bit programs)
//
//  Version: 0.01 prerelease
//
// Authors requests:
//
// -If you don't like or you want to add something please write to me.
//  I would be more than happy to help.
//
// -If you find a bug, it's your duty to mail me.
//
// -Because my 1st language isn't C/C++, I don't know much about it.
//  If anything could be done easier I'm waiting for your mail.
//
//
// Included in this version:
// -Local/Global Variables
// -Local/Global Procedures
// -Structures/Unions
// -Local Labels
//
//
#include "i2s.h"

#ifndef IDA55UP
#define idaapi
#endif
//--------------------------------------------------------------------------
int idaapi init(void)
{
//I used f_PE because this is the first version and it's not tested on any other file type.
	if ( inf.filetype==f_PE )return PLUGIN_OK;		//PE
//
//I tried with others but they fail because they want 16bit nm32 database.
//
//	if ( inf.filetype==f_WIN ) return PLUGIN_OK;	//NE (OS2, )
//	if ( inf.filetype==f_LE ) return PLUGIN_OK;		//LE (VXD)
//	if ( inf.filetype==f_LX ) return PLUGIN_OK;		//LX (VXD)
//	if ( inf.filetype==f_EXE )return PLUGIN_OK;		//MS-DOS
	warning("IDA to SoftIce\n\nSorry, but version: 0.02 supports only PE file types.");
	return PLUGIN_SKIP;
}

//******************************************************************************************************
//******************************************************************************************************
//
//  Main Program
//
//******************************************************************************************************
//******************************************************************************************************

char*	copyright = "NM32 Symbol Format - (C) Copyright Numega Technologies, 1996-1997. All Rights Reserved.  IDA2NMS plugin version: 0.02 release";

//******************************************************************************************************
//******************************************************************************************************
//Global Variables
STTB_S	sttb;
NMTP_S	nmtp;
TYTB_S	tytb;
HSHT_S	hsht;
SYMD_S  symd;
SECTIONS_S	sections;

unsigned long	lineNumberCurrent;	//because this version doesn't support source files
unsigned long	offInSFDefCurrent;	//Offset to sections sourceFiles table in Source Files Definitions.
unsigned long	cSourceFiles;		//number of source files
unsigned long	minEA;				//first ea in segment (code normaly 401000)
									//must be set for every area (check SetSoftice::GetNMSfile)

unsigned long	plugInFlags=0;		//bit flags

//******************************************************************************************************
//******************************************************************************************************
//Local variables
char*	filters = "Numega symbol files (*.nms)\x0 *.nms\x0 All Files (*.*)\x0 *.*\x0";
char*	defExt = "nms";

OPENFILENAME	saveFile = {sizeof(OPENFILENAME),	//lStructSize
							NULL,					//hwndOwner
							NULL,					//hInstance
							filters,				//lpstrFilter
							NULL,					//lpstrCustomFilter
							NULL,					//nMaxCustFilter
							1,						//nFilterIndex
							NULL,					//lpstrFile
							256,					//nMaxFile
							NULL,					//lpstrFileTitle
							NULL,					//nMaxFileTitle
							NULL,					//lpstrInitialDir
							NULL,					//lpstrTitle
							OFN_LONGNAMES|OFN_HIDEREADONLY,	//Flags
							NULL,					//nFileOffset
							NULL,					//nFileExtension
							defExt,					//lpstrDefExt
							NULL,					//lCustData
							NULL,					//lpfnHook
							NULL,					//lpTemplateName
							#if (_WIN32_WINNT >= 0x0500)
							NULL,					//pvReserved;
							NULL,					//dwReserved;
							NULL					//FlagsEx;
							#endif // (_WIN32_WINNT >= 0x0500)
							};


//**********************************************************************************************************************
//**********************************************************************************************************************
//Main
void idaapi run(int arg)
{
	SetSoftIce		ToSice;

	unsigned long*	fileMapped;	//pointer in memory
	char			fileName[256];
	unsigned long	bytesReadWrite;
	HANDLE			hFile;

	unsigned long	flags;

//  arg: 0 = Make NM32 file and load it to SoftIce.      (hotkey: F12)
//       1 = Make NM32 file and save to wanted location. (hotkey: Shift-F12)
//       2 = PlugIn Setup.                               (hotkey: Ctrl-F12)

//--------------------------------------------------------------------------
//Test if SoftIce is loaded.
	if ( 0==(plugInFlags&SOFTICETESTEDALREADY) )
	{
		hFile = CreateFile( "\\\\.\\SICE", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
			                 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		if ( hFile!=INVALID_HANDLE_VALUE )
		{
			CloseHandle(hFile);
			plugInFlags|=SOFTICELOADED;
		}
		else	//is it NT
		{
			hFile = CreateFile( "\\\\.\\NTICE", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
			                     NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			if ( hFile!=INVALID_HANDLE_VALUE )
			{
				CloseHandle(hFile);
				plugInFlags|=SOFTICELOADED;
			}
		}
		plugInFlags|=SOFTICETESTEDALREADY;
	}


//--------------------------------------------------------------------------
//Set setup flags
	flags=CN_T_SYMBOLSONLY | CN_B_STOPATWINMAIN | CN_L_SYBOLSONLY;
	//Normaly they will be saved in idb file.
	//There will/could be a file in plugIn directory i2s.ini that will set
	//users default flags.
	//So when you'll start dissasembled file, plugIn will check if it has
	//p2s setup in it, if not, he will check for i2s.ini. If file would be missing
	//plugIn will start setup window.


//--------------------------------------------------------------------------
	if ( (arg < 2)&&(0==(plugInFlags&PLUGINRUNNING)) )	// Make NM32 file and ....
	{
		plugInFlags|=PLUGINRUNNING;
		ResetGlobalVariables();		//RESET global variables

		if ( FAILED_ != InitializeMemory() )
		{
			ToSice.Set_SoftIce();

			show_wait_box("IDA to SoftIce - Please wait...");
			if ( FAILED_ != (fileMapped=ToSice.GetNMSFile(flags)) )
			{
				hide_wait_box();

				if ( (arg==0)&&( 0!=(plugInFlags&SOFTICELOADED)) )		//load to Softice
				{
					if ( FAILED_==ToSice.LoadNMSFile(fileMapped) )
						warning("An error occured when loading symbols to SoftIce.");
				}
				else
				{
					//set OPENFILENAME
					_splitpath(input_file,NULL,NULL,fileName,NULL);
					saveFile.lpstrFile=fileName;

					//save dbox
					if ( 0!=GetSaveFileName(&saveFile) )
					{
						if ( INVALID_HANDLE_VALUE!=(hFile=CreateFile(fileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL)) )
						{
							if ( 0!=WriteFile(hFile, fileMapped, *(fileMapped+7), &bytesReadWrite, NULL) )
							{
								CloseHandle(hFile);
							}
							else
							{
								warning("Write error!");
							}
						}
						else
						{
							warning("Couldn't create %s", fileName);
						}

					}
				}
			}
			else
			{
				hide_wait_box();
				if ( 0!=(plugInFlags&USERCANCELLED) )
				{
					plugInFlags&=USERNOTCANCELLED;
				}
				else
				{
					warning("PlugIn failed to create nms file.");
				}
				
			}
		}
		FreeMemory();
		plugInFlags&=PLUGINNOTRUNNING;
	}
	else if (arg == 2)
	{
//Setup Window
//i2s.ini will be created by the plugIn.
		warning("Setup is not ready yet in this version.");
	}
}
//******************************************************************************************************
//******************************************************************************************************
//
//  End Of Main Program
//
//******************************************************************************************************
//******************************************************************************************************
//--------------------------------------------------------------------------
//      terminate
//      usually this callback is empty
//
//      IDA will call this function when the user asks to exit.
//      This function won't be called in the case of emergency exits.

void idaapi term(void)
{
}

//   PLUGIN structure definitions
char comment[] = "IDA to SoftIce plugIn. For setup press Ctrl-F12";

char help[] = "IDA to SoftIce plugIn.\n"
              "\n"
              "For conversion press F12.\n"
			  "For saving nms file press Shift-F12.\n"
              "For setup press Ctrl-F12.\n";

//--------------------------------------------------------------------------
// This is the preferred name of the plugin module in the menu system
// The preferred name may be overriden in plugins.cfg file

char wanted_name[] = "IDA to SoftIce";

// This is the preferred hotkey for the plugin module
// The preferred hotkey may be overriden in plugins.cfg file
// Note: IDA won't tell you if the hotkey is not correct
//       It will just disable the hotkey.

char wanted_hotkey[] = "F12";


//--------------------------------------------------------------------------
//
//      PLUGIN DESCRIPTION BLOCK
//
//--------------------------------------------------------------------------

extern "C" plugin_t PLUGIN = {
  IDP_INTERFACE_VERSION,//IDA SDK version
  0,                    // plugin flags
  init,                 // initialize
  term,		            // terminate. this pointer may be NULL.
  run,                  // invoke plugin
  comment,              // long comment about the plugin
                        // it could appear in the status line
                        // or as a hint
  help,                 // multiline help about the plugin
  wanted_name,          // the preferred short name of the plugin
  wanted_hotkey         // the preferred hotkey to run the plugin
};
