[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/clayne/patchdiff2/master/display.cpp [Back]  [Original]

/* 
   Patchdiff2
   Portions (C) 2010 - 2011 Nicolas Pouvesle
   Portions (C) 2007 - 2009 Tenable Network Security, Inc.
   Portions (c) 2018, Chris Eagle (Updates for IDA versions >= 6.7)
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 2 as 
   published by the Free Software Foundation.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see .
*/


#include "precomp.h"

#include "diff.h"
#include "display.h"
#include "os.h"
#include "parser.h"
#include "pgraph.h"
#include "options.h"
#include "system.h"
#include "actions.h"
#include "plugin.h"

static uint32 idaapi sizer_dlist(slist_t *sl) {
   if (sl) {
      return sl->num;
   }
   return 0;
}

static uint32 idaapi sizer_match(void *obj) {
   deng_t *d = (deng_t *)obj;

   return sizer_dlist(d ? d->mlist : NULL);
}

static uint32 idaapi sizer_identical(void *obj) {
   deng_t *d = (deng_t *)obj;

   return sizer_dlist(d ? d->ilist : NULL);
}

static uint32 idaapi sizer_unmatch(void *obj) {
   deng_t *d = (deng_t *)obj;

   return sizer_dlist(d ? d->ulist : NULL);
}

static void idaapi close_window(void *obj) {
   deng_t *d = (deng_t *)obj;

   d->wnum--;
   if (!d->wnum) {
      ipc_close();
   }
   return;
}

/*------------------------------------------------*/
/* function : ui_access_sig                       */
/* description: Compensates for the zero index    */
/*         indicating the header row and performs */
/*         bounds checking in debug               */
/*------------------------------------------------*/

static sig_t *ui_access_sig(slist_t *sl, uint32 n) {
#ifdef _DEBUG
   if (!sl || n == 0 || n > sl->num) {
      error("ui attempted to access siglist out-of-bounds: %p %x\n", sl, n - 1);
      return NULL;
   }
#endif
   return sl->sigs[n - 1];
}

#if IDA_SDK_VERSION mtype);
      qsnprintf(arrptr[1], MAXSTR, "%s", sig->name.c_str());
      qsnprintf(arrptr[2], MAXSTR, "%s", sig->msig->name.c_str());
      qsnprintf(arrptr[3], MAXSTR, "%a", sig->startEA);
      qsnprintf(arrptr[4], MAXSTR, "%a", sig->msig->startEA);
      qsnprintf(arrptr[5], MAXSTR, "%c", sig->id_crc ? '+' : '-');
      qsnprintf(arrptr[6], MAXSTR, "%lx", sig->crc_hash);
      qsnprintf(arrptr[7], MAXSTR, "%lx", sig->msig->crc_hash);
   }
}

/*------------------------------------------------*/
/* function : desc_match                          */
/* description: Fills matched list                */
/*------------------------------------------------*/

static void idaapi desc_match(void *obj, uint32 n, char *const *arrptr) {
   deng_t *d = (deng_t *)obj;

   desc_dlist(d ? d->mlist : NULL, n, arrptr);
}

/*------------------------------------------------*/
/* function : desc_identical                      */
/* description: Fills identical list              */
/*------------------------------------------------*/

static void idaapi desc_identical(void *obj, uint32 n, char *const *arrptr) {
   deng_t *d = (deng_t *)obj;

   desc_dlist(d ? d->ilist : NULL, n, arrptr);
}

/*------------------------------------------------*/
/* function : desc_unmatch                        */
/* description: Fills unmatched list              */
/*------------------------------------------------*/

static void idaapi desc_unmatch(void *obj, uint32 n, char *const *arrptr) {
   int i;

   /* header */
   if (n == 0) {
      for (i = 0; i < qnumber (header_unmatch); i++) {
         qsnprintf(arrptr[i], MAXSTR, "%s", header_unmatch[i]);
      }
   }
   else {
      sig_t *sig = ui_access_sig(((deng_t *)obj)->ulist, n);
      qsnprintf(arrptr[0], MAXSTR, "%u", sig->nfile);
      qsnprintf(arrptr[1], MAXSTR, "%s", sig->name.c_str());
      qsnprintf(arrptr[2], MAXSTR, "%a", sig->startEA);
      qsnprintf(arrptr[3], MAXSTR, "%.8lX", sig->sig);
      qsnprintf(arrptr[4], MAXSTR, "%.8lX", sig->hash);
      qsnprintf(arrptr[5], MAXSTR, "%.8lX", sig->crc_hash);
   }
}
#endif

static void idaapi enter_list(slist_t *sl, uint32 n) {
   jumpto(ui_access_sig(sl, n)->startEA);
   os_copy_to_clipboard(NULL);
}

/*------------------------------------------------*/
/* function : enter_match                         */
/* description: Jumps to code for element n in    */
/*              matched list                      */
/*------------------------------------------------*/

static void idaapi enter_match(void *obj, uint32 n) {
   enter_list(((deng_t *)obj)->mlist, n);
}

/*------------------------------------------------*/
/* function : enter_identical                         */
/* description: Jumps to code for element n in    */
/*              identical list                    */
/*------------------------------------------------*/

static void idaapi enter_identical(void *obj, uint32 n) {
   enter_list(((deng_t *)obj)->ilist, n);
}

/*------------------------------------------------*/
/* function : enter_unmatch                         */
/* description: Jumps to code for element n in    */
/*              unmatched list                    */
/*------------------------------------------------*/

static void idaapi enter_unmatch(void *obj, uint32 n) {
   sig_t *sig = ui_access_sig(((deng_t *)obj)->ulist, n);

   if (sig->nfile == 1) {
      jumpto(sig->startEA);
   }
   else {
      os_copy_to_clipboard(NULL);
   }
}

static uint32 idaapi graph_list(slist_t *sl, uint32 n, options_t *opt) {
   slist_t *sl1 = NULL;
   slist_t *sl2 = NULL;

   msg ("parsing second function...\n");
   sl2 = parse_second_fct(ui_access_sig(sl, n)->msig->startEA, sl->file, opt);
   if (!sl2) {
      msg("Error: FCT2 parsing failed.\n");
      return 0;
   }

   msg ("parsing first function...\n");
#if IDA_SDK_VERSION < 700
   sl1 = parse_fct(ui_access_sig(sl, n)->startEA, dto.graph.s_showpref);
#else
   // dto went away in 7.0, not clear how to replicate above
   sl1 = parse_fct(ui_access_sig(sl, n)->startEA, 0);
#endif
   if (!sl1) {
      msg("Error: FCT1 parsing failed.\n");
      sl2->free_sigs();
      delete sl2;
      return 0;
   }

   sl1->sigs[0]->nfile = 1;
   sl2->sigs[0]->nfile = 2;

   msg ("diffing functions...\n");
   generate_diff(NULL, sl1, sl2, NULL, NULL);

   pgraph_display(sl1, sl2);

   msg ("done!\n");
   return 1;
}

/*------------------------------------------------*/
/* function : graph_match                         */
/* description: Draws graph from element n in     */
/*              matched list                      */
/*------------------------------------------------*/

static void idaapi graph_match(void *obj, uint32 n) {
   slist_t *sl = ((deng_t *)obj)->mlist;
   options_t *opt = ((deng_t *)obj)->opt;

   graph_list(sl, n, opt);

   return;
}

/*------------------------------------------------*/
/* function : graph_identical                     */
/* description: Draws graph from element n in     */
/*              identical list                    */
/*------------------------------------------------*/

static void idaapi graph_identical(void *obj, uint32 n) {
   slist_t *sl = ((deng_t *)obj)->ilist;
   options_t *opt = ((deng_t *)obj)->opt;

   graph_list(sl, n, opt);

   return;
}

/*------------------------------------------------*/
/* function : graph_unmatch                       */
/* description: Draws graph from element n in     */
/*              unmatched list                    */
/*------------------------------------------------*/

static void idaapi graph_unmatch(void *obj, uint32 n) {
   slist_t *sl = NULL;
   slist_t *tmp = ((deng_t *)obj)->ulist;

   if (ui_access_sig(tmp, n)->nfile == 2) {
      msg ("parsing second function...\n");
      sl = parse_second_fct(ui_access_sig(tmp, n)->startEA, tmp->file, ((deng_t *)obj)->opt);
      if (!sl) {
         msg("Error: FCT2 parsing failed.\n");
         return;
      }

      sl->sigs[0]->nfile = 2;
   }
   else {
      msg ("parsing first function...\n");
#if IDA_SDK_VERSION < 700
      sl = parse_fct(ui_access_sig(tmp, n)->startEA, dto.graph.s_showpref);
#else
      // dto went away in 7.0, not clear how to replicate above
      sl = parse_fct(ui_access_sig(tmp, n)->startEA, 0);
#endif
      if (!sl) {
         msg("Error: FCT1 parsing failed.\n");
         return;
      }

      sl->sigs[0]->nfile = 1;
   }

   pgraph_display_one(sl);

   msg ("done!\n");
   return;
}

static uint32 idaapi res_unmatch(deng_t *d, uint32 n, int type) {
   slist_t *sl;

   if (type == 0) {
      sl = d->ilist;
   }
   else {
      sl = d->mlist;
   }

   sig_t *sig = ui_access_sig(sl, n);
   
   sig->nfile = 1;
   sig->msig->nfile = 2;

   d->ulist->add(sig);
   d->ulist->add(sig->msig);

   sig->msig->msig = NULL;
   sig->msig = NULL;

   sl->remove(n - 1);

   // added entries to the unmatched list
   refresh_chooser(title_unmatch);

   // removed an entry from one of the following lists
   if (type == 0) {
      refresh_chooser(title_identical);
   }
   else {
      refresh_chooser(title_match);
   }

   return 1;
}

/*------------------------------------------------*/
/* function : res_iunmatch                        */
/* description: Unmatches element n from identical*/
/*              list                              */
/*------------------------------------------------*/

static uint32 idaapi res_iunmatch(void *obj, uint32 n) {
   return res_unmatch((deng_t *)obj, n, 0);
}

/*------------------------------------------------*/
/* function : res_munmatch                        */
/* description: Unmatches element n from matched  */
/*              list                              */
/*------------------------------------------------*/

static uint32 idaapi res_munmatch(void *obj, uint32 n) {
   return res_unmatch((deng_t *)obj, n, 1);
}

/*------------------------------------------------*/
/* function : propagate_match                     */
/* description: Propagates new matched result if  */
/*              option is set in dialog box       */
/*------------------------------------------------*/

void propagate_match(deng_t *eng, sig_t *s1, sig_t *s2, int options) {
   size_t i;

   if (options) {
      show_wait_box ("PatchDiff is in progress ...");

      slist_t *l1 = new slist_t(eng->ulist->num, eng->ulist->file);
      slist_t *l2 = new slist_t(eng->ulist->num, eng->ulist->file);

      for (i = 0; i < eng->ulist->num; i++) {
         if (!eng->ulist->sigs[i]->msig) {
            if (eng->ulist->sigs[i]->nfile == 1) {
               l1->add(eng->ulist->sigs[i]);
            }
            else {
               l2->add(eng->ulist->sigs[i]);
            }
         }
      }
      generate_diff(NULL, l1, l2, eng->ulist->file, NULL);

      delete l1;
      delete l2;

      hide_wait_box();
   }

   i = 0;
   while (i < eng->ulist->num) {
      s1 = eng->ulist->sigs[i];
      s2 = s1->msig;

      if (!s2) {
         i++;
      }
      else {
         if (s1->nfile == 1) {
            if (sig_equal(s1, s2, DIFF_EQUAL_SIG_HASH)) {
               eng->ilist->add(s1);
            }
            else {
               eng->mlist->add(s1);
            }
         }

         eng->ulist->remove(i);
      }
   }
}

/*------------------------------------------------*/
/* function : res_match                           */
/* description: Matches 2 elements from unmatched */
/*              list                              */
/*------------------------------------------------*/

static uint32 idaapi res_match(void *obj, uint32 n) {
   deng_t *eng = (deng_t *)obj;
   sig_t *s1;
   sig_t *s2;
   int option;
   ea_t ea = BADADDR;
   size_t i;

   const char format[] =
         "STARTITEM 0\n"

         "Set Match\n"
         "\n\n"

         "Options :\n" 
         ">\n\n"
         ;

   option = 1;
   if (AskUsingForm_c(format, &ea, &option)) {
      s1 = ui_access_sig(eng->ulist, n);

      for (i = 0; i < eng->ulist->num; i++) {
         s2 = eng->ulist->sigs[i];

         if (s2->startEA != ea || (s2->nfile == s1->nfile)) {
            continue;
         }
         s1->set_matched_sig(s2, DIFF_MANUAL);
         propagate_match(eng, s1, s2, option);

         // adding a match
         refresh_chooser(title_match);
         // removing a pair of unmatched functions
         refresh_chooser(title_unmatch);

         return 1;
      }

      warning("Address '%a' is not valid.", ea);
      return 0;
   }

   return 1;
}

/*------------------------------------------------*/
/* function : res_mtoi                            */
/* description: Switches element n from matched   */
/*              to identical list                 */
/*------------------------------------------------*/

static uint32 idaapi res_mtoi(void *obj, uint32 n) {
   deng_t *d = (deng_t *)obj;
   sig_t *sig = ui_access_sig(d->mlist, n);

   sig->mtype = sig->msig->mtype = DIFF_MANUAL;

   d->ilist->add(sig);
   d->mlist->remove(n - 1);

   // adding to identical
   refresh_chooser(title_identical);
   // removing from matched
   refresh_chooser(title_match);

   return 1;
}

/*------------------------------------------------*/
/* function : res_itom                            */
/* description: Switches element n from identical */
/*              to matched list                   */
/*------------------------------------------------*/

static uint32 idaapi res_itom(void *obj, uint32 n) {
   deng_t *d = (deng_t *)obj;
   sig_t *sig = ui_access_sig(d->ilist, n);

   sig->mtype = sig->msig->mtype = DIFF_MANUAL;

   d->mlist->add(sig);
   d->ilist->remove(n - 1);

   // removing from identical
   refresh_chooser(title_identical);
   // adding to matched
   refresh_chooser(title_match);

   return 1;
}

/*------------------------------------------------*/
/* function : res_flagged                         */
/* description: Sets element as flagged/unflagged */
/*------------------------------------------------*/

static uint32 idaapi res_flagged(void *obj, uint32 n) {
   sig_t *sig = ui_access_sig(((deng_t *)obj)->mlist, n);

   sig->flag = !sig->flag;

   // flagging only happens on the matched list
   refresh_chooser(title_match);

   return 1;
}

static void transfer_sym(sig_t *sig) {
   sig_t *rhs = sig->msig;
   sig->set_name(rhs->name);
   set_name(sig->startEA, rhs->name.c_str(), SN_NOCHECK | SN_NON_AUTO);
}

static uint32 idaapi transfer_sym_match(void *obj, uint32 n) {
   sig_t *sig = ui_access_sig(((deng_t *)obj)->mlist, n);

   transfer_sym(sig);

   return 1;
}

static uint32 idaapi transfer_sym_identical(void *obj, uint32 n) {
   sig_t *sig = ui_access_sig(((deng_t *)obj)->ilist, n);

   transfer_sym(sig);

   return 1;
}

#if IDA_SDK_VERSION >= 670
//-------------------------------------------------------------------------
int idaapi munmatch_action_handler_t::activate(action_activation_ctx_t *ctx) {
   uint32 n = ctx->chooser_selection.size();
   if (n == 1) {
      n = ctx->chooser_selection[0];
#if IDA_SDK_VERSION < 700
      return res_munmatch(plugin->d_engine, n);
#else
      return res_munmatch(plugin->d_engine, n + 1);  //hack because pre-7.0 choosers index from 1
#endif
   }
   return 0;
}
   
action_state_t idaapi munmatch_action_handler_t::update(action_update_ctx_t *ctx) {
   bool ok = ctx->form_type == BWN_CHOOSER;
   if (ok) {
      //it's a chooser, now make sure it's the correct form
#if IDA_SDK_VERSION < 700
      char name[MAXSTR];
      ok = get_tform_title(ctx->form, name, sizeof(name)) && strneq(name, title_match, qstrlen(title_match));
#else
      qstring title;
      ok = get_widget_title(&title, ctx->widget) && title == title_match;
#endif
   }
   return ok ? AST_ENABLE_FOR_FORM : AST_DISABLE_FOR_FORM;
}

//-------------------------------------------------------------------------
int idaapi identical_action_handler_t::activate(action_activation_ctx_t *ctx) {
   uint32 n = ctx->chooser_selection.size();
   if (n == 1) {
      n = ctx->chooser_selection[0];
#if IDA_SDK_VERSION < 700
      return res_mtoi(plugin->d_engine, n);
#else
      return res_mtoi(plugin->d_engine, n + 1);  //hack because pre-7.0 choosers index from 1
#endif
   }
   return 0;
}

action_state_t idaapi identical_action_handler_t::update(action_update_ctx_t *ctx) {
   bool ok = ctx->form_type == BWN_CHOOSER;
   if (ok) {
      //it's a chooser, now make sure it's the correct form
#if IDA_SDK_VERSION < 700
      char name[MAXSTR];
      ok = get_tform_title(ctx->form, name, sizeof(name)) && strneq(name, title_match, qstrlen(title_match));
#else
      qstring title;
      ok = get_widget_title(&title, ctx->widget) && title == title_match;
#endif
   }
   return ok ? AST_ENABLE_FOR_FORM : AST_DISABLE_FOR_FORM;
}

//-------------------------------------------------------------------------
int idaapi flagunflag_action_handler_t::activate(action_activation_ctx_t *ctx) {
   uint32 n = ctx->chooser_selection.size();
   if (n == 1) {
      n = ctx->chooser_selection[0];
#if IDA_SDK_VERSION < 700
      return res_flagged(plugin->d_engine, n);
#else
      return res_flagged(plugin->d_engine, n + 1);  //hack because pre-7.0 choosers index from 1
#endif
   }
   return 0;
}

action_state_t idaapi flagunflag_action_handler_t::update(action_update_ctx_t *ctx) {
   bool ok = ctx->form_type == BWN_CHOOSER;
   if (ok) {
      //it's a chooser, now make sure it's the correct form
#if IDA_SDK_VERSION < 700
      char name[MAXSTR];
      ok = get_tform_title(ctx->form, name, sizeof(name)) && strneq(name, title_match, qstrlen(title_match));
#else
      qstring title;
      ok = get_widget_title(&title, ctx->widget) && title == title_match;
#endif
   }
   return ok ? AST_ENABLE_FOR_FORM : AST_DISABLE_FOR_FORM;
}

//-------------------------------------------------------------------------
int idaapi msym_action_handler_t::activate(action_activation_ctx_t *ctx) {
   uint32 n = ctx->chooser_selection.size();
   if (n == 1) {
      n = ctx->chooser_selection[0];
#if IDA_SDK_VERSION < 700
      return transfer_sym_match(plugin->d_engine, n);
#else
      return transfer_sym_match(plugin->d_engine, n + 1);  //hack because pre-7.0 choosers index from 1
#endif
   }
   return 0;
}

action_state_t idaapi msym_action_handler_t::update(action_update_ctx_t *ctx) {
   bool ok = ctx->form_type == BWN_CHOOSER;
   if (ok) {
      //it's a chooser, now make sure it's the correct form
#if IDA_SDK_VERSION < 700
      char name[MAXSTR];
      ok = get_tform_title(ctx->form, name, sizeof(name)) && strneq(name, title_match, qstrlen(title_match));
#else
      qstring title;
      ok = get_widget_title(&title, ctx->widget) && title == title_match;
#endif
   }
   return ok ? AST_ENABLE_FOR_FORM : AST_DISABLE_FOR_FORM;
}

//-------------------------------------------------------------------------
int idaapi iunmatch_action_handler_t::activate(action_activation_ctx_t *ctx) {
   uint32 n = ctx->chooser_selection.size();
   if (n == 1) {
      n = ctx->chooser_selection[0];
#if IDA_SDK_VERSION < 700
      return res_iunmatch(plugin->d_engine, n);
#else
      return res_iunmatch(plugin->d_engine, n + 1);  //hack because pre-7.0 choosers index from 1
#endif
   }
   return 0;
}

action_state_t idaapi iunmatch_action_handler_t::update(action_update_ctx_t *ctx) {
   bool ok = ctx->form_type == BWN_CHOOSER;
   if (ok) {
#if IDA_SDK_VERSION < 700
      char name[MAXSTR];
      ok = get_tform_title(ctx->form, name, sizeof(name)) && strneq(name, title_identical, qstrlen(title_match));
#else
      qstring title;
      ok = get_widget_title(&title, ctx->widget) && title == title_identical;
#endif
   }
   return ok ? AST_ENABLE_FOR_FORM : AST_DISABLE_FOR_FORM;
}

//-------------------------------------------------------------------------
int idaapi itom_action_handler_t::activate(action_activation_ctx_t *ctx) {
   uint32 n = ctx->chooser_selection.size();
   if (n == 1) {
      n = ctx->chooser_selection[0];
#if IDA_SDK_VERSION < 700
      return res_itom(plugin->d_engine, n);
#else
      return res_itom(plugin->d_engine, n + 1);  //hack because pre-7.0 choosers index from 1
#endif
   }
   return 0;
}

action_state_t idaapi itom_action_handler_t::update(action_update_ctx_t *ctx) {
   bool ok = ctx->form_type == BWN_CHOOSER;
   if (ok) {
      //it's a chooser, now make sure it's the correct form
#if IDA_SDK_VERSION < 700
      char name[MAXSTR];
      ok = get_tform_title(ctx->form, name, sizeof(name)) && strneq(name, title_identical, qstrlen(title_match));
#else
      qstring title;
      ok = get_widget_title(&title, ctx->widget) && title == title_identical;
#endif
   }
   return ok ? AST_ENABLE_FOR_FORM : AST_DISABLE_FOR_FORM;
}

//-------------------------------------------------------------------------
int idaapi isym_action_handler_t::activate(action_activation_ctx_t *ctx) {
   uint32 n = ctx->chooser_selection.size();
   if (n == 1) {
      n = ctx->chooser_selection[0];
#if IDA_SDK_VERSION < 700
      return transfer_sym_identical(plugin->d_engine, n);
#else
      return transfer_sym_identical(plugin->d_engine, n + 1);  //hack because pre-7.0 choosers index from 1
#endif
   }
   return 0;
}

action_state_t idaapi isym_action_handler_t::update(action_update_ctx_t *ctx) {
   bool ok = ctx->form_type == BWN_CHOOSER;
   if (ok) {
      //it's a chooser, now make sure it's the correct form
#if IDA_SDK_VERSION < 700
      char name[MAXSTR];
      ok = get_tform_title(ctx->form, name, sizeof(name)) && strneq(name, title_identical, qstrlen(title_match));
#else
      qstring title;
      ok = get_widget_title(&title, ctx->widget) && title == title_identical;
#endif
   }
   return ok ? AST_ENABLE_FOR_FORM : AST_DISABLE_FOR_FORM;
}

//-------------------------------------------------------------------------
int idaapi match_action_handler_t::activate(action_activation_ctx_t *ctx) {
   uint32 n = ctx->chooser_selection.size();
   if (n == 1) {
      n = ctx->chooser_selection[0];
#if IDA_SDK_VERSION < 700
      return res_match(plugin->d_engine, n);
#else
      return res_match(plugin->d_engine, n + 1);  //hack because pre-7.0 choosers index from 1
#endif
   }
   return 0;
}

action_state_t idaapi match_action_handler_t::update(action_update_ctx_t *ctx) {
   bool ok = ctx->form_type == BWN_CHOOSER;
   if (ok) {
      //it's a chooser, now make sure it's the correct form
#if IDA_SDK_VERSION < 700
      char name[MAXSTR];
      ok = get_tform_title(ctx->form, name, sizeof(name)) && strneq(name, title_unmatch, qstrlen(title_match));
#else
      qstring title;
      ok = get_widget_title(&title, ctx->widget) && title == title_unmatch;
#endif
   }
   return ok ? AST_ENABLE_FOR_FORM : AST_DISABLE_FOR_FORM;
}

#endif

#if IDA_SDK_VERSION >= 700

static void idaapi desc_dlist(slist_t *sl, uint32 n, qstrvec_t *cols_) {
   qstrvec_t &cols = *cols_;
   sig_t *sig = ui_access_sig(sl, n + 1); //hack because pre-7.0 choosers index from 1
   cols[0].sprnt("%u", sig->mtype);
   cols[1].sprnt("%s", sig->name.c_str());
   cols[2].sprnt("%s", sig->msig->name.c_str());
   cols[3].sprnt("%a", sig->startEA);
   cols[4].sprnt("%a", sig->msig->startEA);
   cols[5].sprnt("%c", sig->id_crc ? '+' : '-');
   cols[6].sprnt("%lx", sig->crc_hash);
   cols[7].sprnt("%lx", sig->msig->crc_hash);
}

//-------------------------------------------------------------------------
struct matched_chooser_t : public chooser_t {
private:
   deng_t *eng;
public:
   // this object must be allocated using `new`
   matched_chooser_t(deng_t *eng_);

  // function that is used to decide whether a new chooser should be opened
  // or we can use the existing one.
  // The contents of the window are completely determined by its title
   virtual const void *get_obj_id(size_t *len) const {
      *len = strlen(title);
      return title;
   }

   // function that returns number of lines in the list
   virtual size_t idaapi get_count() const {
      return sizer_dlist(eng ? eng->mlist : NULL);
   }

   // function that generates the list line
   virtual void idaapi get_row(qstrvec_t *cols, int *icon_, chooser_item_attrs_t *attrs, size_t n) const;

   // function that is called when the user hits Enter
   virtual cbret_t idaapi enter(size_t n) {
      enter_list(eng->mlist, n + 1);  //hack because pre-7.0 choosers index from 1
      return cbret_t(); // nothing changed
   }
   
   virtual cbret_t idaapi edit(size_t n) {
      graph_match(eng, n + 1); //hack because pre-7.0 choosers index from 1
      return cbret_t(); // nothing changed
   }

   virtual void idaapi closed();
   
};

inline matched_chooser_t::matched_chooser_t(deng_t *eng_) :
      chooser_t(CH_ATTRS | CH_CAN_EDIT, qnumber(widths_match), widths_match, header_match, title_match) {
   eng = eng_;  
   popup_names[POPUP_EDIT] = "Display Graphs";
}

void idaapi matched_chooser_t::get_row(qstrvec_t *cols_, int *, chooser_item_attrs_t *, size_t n) const {
   desc_dlist(eng ? eng->mlist : NULL, n, cols_);
}

void idaapi matched_chooser_t::closed() {
   close_window(eng);
}

static matched_chooser_t *matched_chooser;

//-------------------------------------------------------------------------
struct identical_chooser_t : public chooser_t {
private:
   deng_t *eng;
public:
   // this object must be allocated using `new`
   identical_chooser_t(deng_t *eng_);

  // function that is used to decide whether a new chooser should be opened
  // or we can use the existing one.
  // The contents of the window are completely determined by its title
   virtual const void *get_obj_id(size_t *len) const {
      *len = strlen(title);
      return title;
   }

   // function that returns number of lines in the list
   virtual size_t idaapi get_count() const {
      return sizer_dlist(eng ? eng->ilist : NULL);
   }

   // function that generates the list line
   virtual void idaapi get_row(qstrvec_t *cols, int *icon_, chooser_item_attrs_t *attrs, size_t n) const;

   // function that is called when the user hits Enter
   virtual cbret_t idaapi enter(size_t n) {
      enter_list(eng->ilist, n + 1); //hack because pre-7.0 choosers index from 1
      return cbret_t(); // nothing changed
   }

   virtual cbret_t idaapi edit(size_t n) {
      graph_identical(eng, n + 1);  //hack because pre-7.0 choosers index from 1
      return cbret_t(); // nothing changed
   }

   virtual void idaapi closed() {
      close_window(eng);
   }
};

inline identical_chooser_t::identical_chooser_t(deng_t *eng_) :
      chooser_t(CH_ATTRS | CH_CAN_EDIT, qnumber(widths_match), widths_match, header_match, title_identical) {
   eng = eng_;  
   popup_names[POPUP_EDIT] = "Display Graphs";
}

void idaapi identical_chooser_t::get_row(qstrvec_t *cols_, int *, chooser_item_attrs_t *, size_t n) const {
   desc_dlist(eng ? eng->ilist : NULL, n, cols_);
}

static identical_chooser_t *identical_chooser;

//-------------------------------------------------------------------------
struct unmatched_chooser_t : public chooser_t {
private:
   deng_t *eng;
public:
   // this object must be allocated using `new`
   unmatched_chooser_t(deng_t *eng_);

  // function that is used to decide whether a new chooser should be opened
  // or we can use the existing one.
  // The contents of the window are completely determined by its title
   virtual const void *get_obj_id(size_t *len) const {
      *len = strlen(title);
      return title;
   }

   // function that returns number of lines in the list
   virtual size_t idaapi get_count() const {
      return sizer_dlist(eng ? eng->ulist : NULL);
   }

   // function that generates the list line
   virtual void idaapi get_row(qstrvec_t *cols, int *icon_, chooser_item_attrs_t *attrs, size_t n) const;

   // function that is called when the user hits Enter
   virtual cbret_t idaapi enter(size_t n) {
      sig_t *sig = ui_access_sig(eng->ulist, n + 1);  //hack because pre-7.0 choosers index from 1
      
      if (sig->nfile == 1) {
         jumpto(sig->startEA);
      }
      else {
         os_copy_to_clipboard(NULL);
      }

      return cbret_t(); // nothing changed
   }

   virtual cbret_t idaapi edit(size_t n) {
      graph_unmatch(eng, n + 1);  //hack because pre-7.0 choosers index from 1
      return cbret_t(); // nothing changed
   }

   virtual void idaapi closed() {
      close_window(eng);
   }
};

inline unmatched_chooser_t::unmatched_chooser_t(deng_t *eng_) :
      chooser_t(CH_ATTRS | CH_CAN_EDIT, qnumber(widths_unmatch), widths_unmatch, header_unmatch, title_unmatch) {
   eng = eng_;  
   popup_names[POPUP_EDIT] = "Display Graph";
}

void idaapi unmatched_chooser_t::get_row(qstrvec_t *cols_, int *, chooser_item_attrs_t *, size_t n) const {
   qstrvec_t &cols = *cols_;
   sig_t *sig = ui_access_sig(eng->ulist, n + 1);  //hack because pre-7.0 choosers index from 1
   cols[0].sprnt("%u", sig->nfile);
   cols[1].sprnt("%s", sig->name.c_str());
   cols[2].sprnt("%a", sig->startEA);
   cols[3].sprnt("%.8lX", sig->sig);
   cols[4].sprnt("%.8lX", sig->hash);
   cols[5].sprnt("%.8lX", sig->crc_hash);
}

static unmatched_chooser_t *unmatched_chooser;

#endif

/*------------------------------------------------*/
/* function : display_matched                     */
/* description: Displays matched list             */
/*------------------------------------------------*/

static void display_matched(deng_t *eng) {
#if IDA_SDK_VERSION choose(chooser_t::NO_SELECTION);
   }
#endif

   eng->wnum++;
   
#if IDA_SDK_VERSION mlist, n)->flag == 1) {
               attrs->color = 0x908070;
            }
         }
      }
   }

   return 0;
}

/*------------------------------------------------*/
/* function : display_results                     */
/* description: Displays diff results             */
/*------------------------------------------------*/

void display_results(pd_plugmod_t *plugin) {

#if IDA_SDK_VERSION >= 670
   register_action(plugin->munmatch_action);
   register_action(plugin->identical_action);
   register_action(plugin->flagunflag_action);
   register_action(plugin->msym_action);
   register_action(plugin->iunmatch_action);
   register_action(plugin->itom_action);
   register_action(plugin->isym_action);
   register_action(plugin->match_action);
#endif

   hook_to_notification_point(HT_UI, ui_callback, NULL);

   display_matched(plugin->d_engine);
   display_unmatched(plugin->d_engine);
   display_identical(plugin->d_engine);
}

Web Proxy Viewer  |  New URL  |  Original Page