update to ida 7.6, add builds
This commit is contained in:
282
idasdk76/plugins/custview/custview.cpp
Normal file
282
idasdk76/plugins/custview/custview.cpp
Normal file
@@ -0,0 +1,282 @@
|
||||
/* Custom viewer sample plugin.
|
||||
* Copyright (c) 2007 by Ilfak Guilfanov, ig@hexblog.com
|
||||
* Feel free to do whatever you want with this code.
|
||||
*
|
||||
* This sample plugin demonstates how to create and manipulate a simple
|
||||
* custom viewer in IDA v5.1
|
||||
*
|
||||
* Custom viewers allow you to create a view which displays colored lines.
|
||||
* These colored lines are dynamically created by callback functions.
|
||||
*
|
||||
* Custom viewers are used in IDA itself to display
|
||||
* the disassembly listng, structure, and enumeration windows.
|
||||
*
|
||||
* This sample plugin just displays several sample lines on the screen.
|
||||
* It displays a hint with the current line number.
|
||||
* The right-click menu contains one sample command.
|
||||
* It reacts to one hotkey.
|
||||
*
|
||||
* This plugin uses the simpleline_place_t class for the locations.
|
||||
* Custom viewers can use any decendant of the place_t class.
|
||||
* The place_t is responsible for supplying data to the viewer.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#include <ida.hpp>
|
||||
#include <idp.hpp>
|
||||
#include <loader.hpp>
|
||||
#include <kernwin.hpp>
|
||||
|
||||
#define ACTION_NAME "custview:SampleMenuItem"
|
||||
|
||||
struct plugin_ctx_t;
|
||||
struct sample_action_t : public action_handler_t
|
||||
{
|
||||
plugin_ctx_t &plg;
|
||||
sample_action_t(plugin_ctx_t &p) : plg(p) {}
|
||||
virtual int idaapi activate(action_activation_ctx_t *) override;
|
||||
virtual action_state_t idaapi update(action_update_ctx_t *) override
|
||||
{
|
||||
return AST_ENABLE_ALWAYS;
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static struct
|
||||
{
|
||||
const char *text;
|
||||
bgcolor_t color;
|
||||
} const sample_text[] =
|
||||
{
|
||||
{ "This is a sample text", 0xFFFFFF },
|
||||
{ "It will be displayed in the custom view", 0xFFC0C0 },
|
||||
{ COLSTR("This line will be colored as erroneous", SCOLOR_ERROR), 0xC0FFC0 },
|
||||
{ COLSTR("Every", SCOLOR_AUTOCMT) " "
|
||||
COLSTR("word", SCOLOR_DNAME) " "
|
||||
COLSTR("can", SCOLOR_IMPNAME) " "
|
||||
COLSTR("be", SCOLOR_NUMBER) " "
|
||||
COLSTR("colored!", SCOLOR_EXTRA), 0xC0C0FF },
|
||||
{ " No limit on the number of lines.", 0xC0FFFF },
|
||||
};
|
||||
|
||||
// Structure to keep all information about the our sample view
|
||||
struct sample_info_t
|
||||
{
|
||||
TWidget *cv;
|
||||
strvec_t sv;
|
||||
sample_info_t() : cv(NULL) {}
|
||||
};
|
||||
|
||||
struct plugin_ctx_t : public plugmod_t, public event_listener_t
|
||||
{
|
||||
sample_info_t *si = NULL;
|
||||
const sample_info_t *last_si = NULL;
|
||||
|
||||
sample_action_t sample_ah = sample_action_t(*this);
|
||||
const action_desc_t sample_action = ACTION_DESC_LITERAL_PLUGMOD(
|
||||
ACTION_NAME,
|
||||
"Sample menu item",
|
||||
&sample_ah,
|
||||
this,
|
||||
"N",
|
||||
NULL,
|
||||
-1);
|
||||
|
||||
virtual bool idaapi run(size_t) override;
|
||||
virtual ssize_t idaapi on_event(ssize_t code, va_list va) override;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// get the word under the (keyboard or mouse) cursor
|
||||
static bool get_current_word(TWidget *v, bool mouse, qstring &word)
|
||||
{
|
||||
// query the cursor position
|
||||
int x, y;
|
||||
if ( get_custom_viewer_place(v, mouse, &x, &y) == NULL )
|
||||
return false;
|
||||
|
||||
// query the line at the cursor
|
||||
qstring buf;
|
||||
tag_remove(&buf, get_custom_viewer_curline(v, mouse));
|
||||
if ( x >= buf.length() )
|
||||
return false;
|
||||
|
||||
// find the beginning of the word
|
||||
char *ptr = buf.begin() + x;
|
||||
while ( ptr > buf.begin() && !qisspace(ptr[-1]) )
|
||||
ptr--;
|
||||
|
||||
// find the end of the word
|
||||
char *begin = ptr;
|
||||
ptr = buf.begin() + x;
|
||||
while ( !qisspace(*ptr) && *ptr != '\0' )
|
||||
ptr++;
|
||||
|
||||
word = qstring(begin, ptr-begin);
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int idaapi sample_action_t::activate(action_activation_ctx_t *)
|
||||
{
|
||||
qstring word;
|
||||
if ( !get_current_word(plg.last_si->cv, false, word) )
|
||||
return 0;
|
||||
|
||||
info("The current word is: %s", word.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Keyboard callback
|
||||
static bool idaapi ct_keyboard(TWidget * /*v*/, int key, int shift, void *ud)
|
||||
{
|
||||
if ( shift == 0 )
|
||||
{
|
||||
sample_info_t *si = (sample_info_t *)ud;
|
||||
switch ( key )
|
||||
{
|
||||
case 'N':
|
||||
warning("The hotkey 'N' has been pressed");
|
||||
return true;
|
||||
case IK_ESCAPE:
|
||||
close_widget(si->cv, WCLS_SAVE | WCLS_CLOSE_LATER);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// This callback will be called each time the keyboard cursor position
|
||||
// is changed
|
||||
static void idaapi ct_curpos(TWidget *v, void *)
|
||||
{
|
||||
qstring word;
|
||||
if ( get_current_word(v, false, word) )
|
||||
msg("Current word is: %s\n", word.c_str());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list va)
|
||||
{
|
||||
switch ( code )
|
||||
{
|
||||
// how to implement a simple hint callback
|
||||
case ui_get_custom_viewer_hint:
|
||||
{
|
||||
qstring &hint = *va_arg(va, qstring *);
|
||||
TWidget *viewer = va_arg(va, TWidget *);
|
||||
place_t *place = va_arg(va, place_t *);
|
||||
int *important_lines = va_arg(va, int *);
|
||||
if ( si->cv == viewer ) // our viewer
|
||||
{
|
||||
if ( place == NULL )
|
||||
return 0;
|
||||
simpleline_place_t *spl = (simpleline_place_t *)place;
|
||||
hint.cat_sprnt("Hint for line %u\n", spl->n);
|
||||
*important_lines += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ui_widget_invisible:
|
||||
{
|
||||
TWidget *f = va_arg(va, TWidget *);
|
||||
if ( f == si->cv )
|
||||
{
|
||||
delete si;
|
||||
si = nullptr;
|
||||
unhook_event_listener(HT_UI, this);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ui_populating_widget_popup:
|
||||
{
|
||||
TWidget *f = va_arg(va, TWidget *);
|
||||
if ( f == si->cv )
|
||||
{
|
||||
TPopupMenu *p = va_arg(va, TPopupMenu *);
|
||||
// Create right-click menu on the fly
|
||||
attach_action_to_popup(f, p, ACTION_NAME);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static const custom_viewer_handlers_t handlers(
|
||||
ct_keyboard,
|
||||
NULL, // popup
|
||||
NULL, // mouse_moved
|
||||
NULL, // click
|
||||
NULL, // dblclick
|
||||
ct_curpos,
|
||||
NULL, // close
|
||||
NULL, // help
|
||||
NULL);// adjust_place
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Create a custom view window
|
||||
bool idaapi plugin_ctx_t::run(size_t)
|
||||
{
|
||||
TWidget *widget = find_widget("Sample custom view");
|
||||
if ( widget != NULL )
|
||||
{
|
||||
activate_widget(widget, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// allocate block to hold info about our sample view
|
||||
si = new sample_info_t();
|
||||
last_si = si;
|
||||
// prepare the data to display. we could prepare it on the fly too.
|
||||
// but for that we have to use our own custom place_t class decendant.
|
||||
for ( int i=0; i < qnumber(sample_text); i++ )
|
||||
{
|
||||
si->sv.push_back(simpleline_t("")); // add empty line
|
||||
si->sv.push_back(simpleline_t(sample_text[i].text));
|
||||
si->sv.back().bgcolor = sample_text[i].color;
|
||||
}
|
||||
// create two place_t objects: for the minimal and maximal locations
|
||||
simpleline_place_t s1;
|
||||
simpleline_place_t s2(si->sv.size()-1);
|
||||
// create a custom viewer
|
||||
si->cv = create_custom_viewer("Sample custom view", &s1, &s2, &s1, NULL, &si->sv, &handlers, si);
|
||||
// also set the ui event callback
|
||||
hook_event_listener(HT_UI, this);
|
||||
// finally display the form on the screen
|
||||
display_widget(si->cv, WOPN_DP_TAB|WOPN_RESTORE);
|
||||
|
||||
// Register the action. This one will be attached
|
||||
// live, to the popup menu.
|
||||
register_action(sample_action);
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static plugmod_t *idaapi init()
|
||||
{
|
||||
return new plugin_ctx_t;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// PLUGIN DESCRIPTION BLOCK
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
plugin_t PLUGIN =
|
||||
{
|
||||
IDP_INTERFACE_VERSION,
|
||||
PLUGIN_MULTI, // plugin flags
|
||||
init, // initialize
|
||||
|
||||
nullptr,
|
||||
nullptr,
|
||||
|
||||
"", // long comment about the plugin
|
||||
"", // multiline help about the plugin
|
||||
"Sample custview", // the preferred short name of the plugin
|
||||
"" // the preferred hotkey to run the plugin
|
||||
};
|
||||
11
idasdk76/plugins/custview/makefile
Normal file
11
idasdk76/plugins/custview/makefile
Normal file
@@ -0,0 +1,11 @@
|
||||
PROC=custview
|
||||
|
||||
include ../plugin.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)custview$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \
|
||||
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
|
||||
$(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \
|
||||
$(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
custview.cpp
|
||||
Reference in New Issue
Block a user