Remove unneeded includes from ui folder
[metze/wireshark/wip.git] / ui / gtk / dcerpc_stat.c
1 /* dcerpc_stat.c
2  * dcerpc_stat   2002 Ronnie Sahlberg
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 /* This module provides rpc call/reply SRT statistics to Wireshark,
24  * and displays them graphically.
25  * It is only used by Wireshark and not tshark
26  *
27  * It serves as an example on how to use the tap api.
28  */
29
30 #include "config.h"
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <gtk/gtk.h>
36
37 #include <epan/packet_info.h>
38 #include <epan/stat_tap_ui.h>
39 #include <epan/tap.h>
40 #include <epan/dissectors/packet-dcerpc.h>
41
42
43 #include "ui/simple_dialog.h"
44
45 #include "ui/gtk/dlg_utils.h"
46 #include "ui/gtk/gui_utils.h"
47 #include "ui/gtk/filter_dlg.h"
48 #include "ui/gtk/stock_icons.h"
49 #include "ui/gtk/service_response_time_table.h"
50 #include "ui/gtk/gtkglobals.h"
51 #include "ui/gtk/main.h"
52 #include "ui/gtk/filter_autocomplete.h"
53
54
55 void register_tap_listener_gtkdcerpcstat(void);
56
57 /* used to keep track of the statistics for an entire program interface */
58 typedef struct _dcerpcstat_t {
59         GtkWidget *win;
60         srt_stat_table srt_table;
61         const char *prog;
62         e_uuid_t uuid;
63         guint16 ver;
64         int num_procedures;
65 } dcerpcstat_t;
66
67
68 static gboolean
69 uuid_equal(e_uuid_t *uuid1, e_uuid_t *uuid2)
70 {
71         if( (uuid1->Data1    != uuid2->Data1)
72           ||(uuid1->Data2    != uuid2->Data2)
73           ||(uuid1->Data3    != uuid2->Data3)
74           ||(uuid1->Data4[0] != uuid2->Data4[0])
75           ||(uuid1->Data4[1] != uuid2->Data4[1])
76           ||(uuid1->Data4[2] != uuid2->Data4[2])
77           ||(uuid1->Data4[3] != uuid2->Data4[3])
78           ||(uuid1->Data4[4] != uuid2->Data4[4])
79           ||(uuid1->Data4[5] != uuid2->Data4[5])
80           ||(uuid1->Data4[6] != uuid2->Data4[6])
81           ||(uuid1->Data4[7] != uuid2->Data4[7]) ){
82                 return FALSE;
83         }
84         return TRUE;
85 }
86
87 static char *
88 dcerpcstat_gen_title(dcerpcstat_t *rs)
89 {
90         char *title;
91         char *display_name;
92
93         display_name = cf_get_display_name(&cfile);
94         title = g_strdup_printf("DCE-RPC Service Response Time statistics for %s major version %u: %s", rs->prog, rs->ver, display_name);
95         g_free(display_name);
96         return title;
97 }
98
99 static void
100 dcerpcstat_set_title(dcerpcstat_t *rs)
101 {
102         char *title;
103
104         title = dcerpcstat_gen_title(rs);
105         gtk_window_set_title(GTK_WINDOW(rs->win), title);
106         g_free(title);
107 }
108
109 static void
110 dcerpcstat_reset(void *rs_arg)
111 {
112         dcerpcstat_t *rs = (dcerpcstat_t *)rs_arg;
113
114         reset_srt_table_data(&rs->srt_table);
115         dcerpcstat_set_title(rs);
116 }
117
118
119 static gboolean
120 dcerpcstat_packet(void *rs_arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ri_arg)
121 {
122         dcerpcstat_t *rs = (dcerpcstat_t *)rs_arg;
123         const dcerpc_info *ri = (dcerpc_info *)ri_arg;
124
125         if(!ri->call_data){
126                 return FALSE;
127         }
128         if(!ri->call_data->req_frame){
129                 /* we have not seen the request so we don't know the delta*/
130                 return FALSE;
131         }
132         if(ri->call_data->opnum >= rs->num_procedures){
133                 /* don't handle this since it's outside of known table */
134                 return FALSE;
135         }
136
137         /* we are only interested in reply packets */
138         if(ri->ptype != PDU_RESP){
139                 return FALSE;
140         }
141
142         /* we are only interested in certain program/versions */
143         if( (!uuid_equal( (&ri->call_data->uuid), (&rs->uuid)))
144           ||(ri->call_data->ver != rs->ver)){
145                 return FALSE;
146         }
147
148
149         add_srt_table_data(&rs->srt_table, ri->call_data->opnum, &ri->call_data->req_time, pinfo);
150
151
152         return TRUE;
153 }
154
155 static void
156 dcerpcstat_draw(void *rs_arg)
157 {
158         dcerpcstat_t *rs = (dcerpcstat_t *)rs_arg;
159
160         draw_srt_table_data(&rs->srt_table);
161 }
162
163 static void
164 win_destroy_cb(GtkWindow *win _U_, gpointer data)
165 {
166         dcerpcstat_t *rs = (dcerpcstat_t *)data;
167
168         remove_tap_listener(rs);
169
170         free_srt_table_data(&rs->srt_table);
171         g_free(rs);
172 }
173
174 /* When called, this function will create a new instance of gtk-dcerpcstat.
175  */
176 static void
177 gtk_dcerpcstat_init(const char *opt_arg, void* userdata _U_)
178 {
179         dcerpcstat_t *rs;
180         guint32 i, max_procs;
181         char *title_string;
182         char *filter_string;
183         GtkWidget *vbox;
184         GtkWidget *stat_label;
185         GtkWidget *filter_label;
186         GtkWidget *bbox;
187         GtkWidget *close_bt;
188         dcerpc_sub_dissector *procs;
189         e_uuid_t uuid;
190         guint d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
191         int major, minor;
192         guint16 ver;
193         int pos = 0;
194         const char *filter = NULL;
195         GString *error_string;
196         int hf_opnum;
197
198         /*
199          * XXX - DCE RPC statistics are maintained only by major version,
200          * not by major and minor version, so the minor version number is
201          * ignored.
202          *
203          * Should we just stop supporting minor version numbers here?
204          * Or should we allow it to be omitted?  Or should we keep
205          * separate statistics for different minor version numbers,
206          * and allow the minor version number to be omitted, and
207          * report aggregate statistics for all minor version numbers
208          * if it's omitted?
209          */
210         if(sscanf(
211                    opt_arg,
212                    "dcerpc,srt,%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d,%n",
213                    &d1,&d2,&d3,&d40,&d41,&d42,&d43,&d44,&d45,&d46,&d47,&major,&minor,&pos)
214            == 13) {
215                 uuid.Data1    = d1;
216                 uuid.Data2    = d2;
217                 uuid.Data3    = d3;
218                 uuid.Data4[0] = d40;
219                 uuid.Data4[1] = d41;
220                 uuid.Data4[2] = d42;
221                 uuid.Data4[3] = d43;
222                 uuid.Data4[4] = d44;
223                 uuid.Data4[5] = d45;
224                 uuid.Data4[6] = d46;
225                 uuid.Data4[7] = d47;
226                 if(pos) {
227                         filter = opt_arg+pos;
228                 } else {
229                         filter = NULL;
230                 }
231         } else {
232                 fprintf(stderr, "wireshark: invalid \"-z dcerpc,srt,<uuid>,<major version>.<minor version>[,<filter>]\" argument\n");
233                 exit(1);
234         }
235         if ((major < 0) || (major > 65535)) {
236                 fprintf(stderr,"wireshark: dcerpcstat_init() Major version number %d is invalid - must be positive and <= 65535\n", major);
237                 exit(1);
238         }
239         if ((minor < 0) || (minor > 65535)) {
240                 fprintf(stderr,"wireshark: dcerpcstat_init() Minor version number %d is invalid - must be positive and <= 65535\n", minor);
241                 exit(1);
242         }
243         ver = major;
244
245         rs = (dcerpcstat_t *)g_malloc(sizeof(dcerpcstat_t));
246         rs->prog = dcerpc_get_proto_name(&uuid, ver);
247         if(!rs->prog){
248                 g_free(rs);
249                 fprintf(stderr,
250                         "wireshark: dcerpcstat_init() Protocol with uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x v%u not supported\n",
251                         uuid.Data1,uuid.Data2,uuid.Data3,uuid.Data4[0],uuid.Data4[1],uuid.Data4[2],uuid.Data4[3],uuid.Data4[4],uuid.Data4[5],uuid.Data4[6],uuid.Data4[7],ver);
252                 exit(1);
253         }
254         hf_opnum = dcerpc_get_proto_hf_opnum(&uuid, ver);
255         procs    = dcerpc_get_proto_sub_dissector(&uuid, ver);
256         rs->uuid = uuid;
257         rs->ver  = ver;
258
259         rs->win  = dlg_window_new("dcerpc-stat");  /* transient_for top_level */
260         gtk_window_set_destroy_with_parent(GTK_WINDOW(rs->win), TRUE);
261
262         dcerpcstat_set_title(rs);
263         gtk_window_set_default_size(GTK_WINDOW(rs->win), 550, 400);
264
265         vbox =ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 3, FALSE);
266         gtk_container_add(GTK_CONTAINER(rs->win), vbox);
267         gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
268
269         title_string = dcerpcstat_gen_title(rs);
270         stat_label   = gtk_label_new(title_string);
271         g_free(title_string);
272         gtk_box_pack_start(GTK_BOX(vbox), stat_label, FALSE, FALSE, 0);
273
274         filter_string = g_strdup_printf("Filter: %s",filter ? filter : "");
275         filter_label  = gtk_label_new(filter_string);
276         g_free(filter_string);
277         gtk_label_set_line_wrap(GTK_LABEL(filter_label), TRUE);
278         gtk_box_pack_start(GTK_BOX(vbox), filter_label, FALSE, FALSE, 0);
279
280         for(i=0,max_procs=0;procs[i].name;i++){
281                 if(procs[i].num>max_procs){
282                         max_procs = procs[i].num;
283                 }
284         }
285         rs->num_procedures = max_procs+1;
286
287         /* We must display TOP LEVEL Widget before calling init_srt_table() */
288         gtk_widget_show_all(rs->win);
289
290         if(hf_opnum != -1){
291                 init_srt_table(&rs->srt_table, max_procs+1, vbox, proto_registrar_get_nth(hf_opnum)->abbrev);
292         } else {
293                 init_srt_table(&rs->srt_table, max_procs+1, vbox, NULL);
294         }
295
296         for(i=0;i<(max_procs+1);i++){
297                 int j;
298                 const char *proc_name;
299
300                 proc_name = "unknown";
301                 for(j=0;procs[j].name;j++){
302                         if (procs[j].num == i){
303                                 proc_name = procs[j].name;
304                         }
305                 }
306
307                 init_srt_table_row(&rs->srt_table, i, proc_name);
308         }
309
310
311         error_string = register_tap_listener("dcerpc", rs, filter, 0, dcerpcstat_reset, dcerpcstat_packet, dcerpcstat_draw);
312         if(error_string){
313                 /* error, we failed to attach to the tap. clean up */
314                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
315                 g_string_free(error_string, TRUE);
316                 free_srt_table_data(&rs->srt_table);
317                 g_free(rs);
318                 return;
319         }
320
321         /* Button row. */
322         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
323         gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
324
325         close_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
326         window_set_cancel_button(rs->win, close_bt, window_cancel_button_cb);
327
328         g_signal_connect(rs->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
329         g_signal_connect(rs->win, "destroy",      G_CALLBACK(win_destroy_cb), rs);
330
331         gtk_widget_show_all(rs->win);
332         window_present(rs->win);
333
334         cf_retap_packets(&cfile);
335         gdk_window_raise(gtk_widget_get_window(rs->win));
336 }
337
338
339
340 static e_uuid_t          *dcerpc_uuid_program;
341 static guint16            dcerpc_version;
342 static GtkWidget         *dlg = NULL;
343 static GtkWidget         *filter_entry;
344 static dcerpc_uuid_key   *current_uuid_key;
345 static dcerpc_uuid_value *current_uuid_value;
346 static dcerpc_uuid_key   *new_uuid_key;
347 static dcerpc_uuid_value *new_uuid_value;
348
349 static void
350 dcerpcstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
351 {
352         GString *str;
353         const char *filter;
354
355         if (dcerpc_uuid_program == NULL) {
356                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Please select a program");
357                 return;
358         }
359         str = g_string_new("dcerpc,srt");
360         g_string_append_printf(str,
361             ",%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%u.%u",
362             dcerpc_uuid_program->Data1, dcerpc_uuid_program->Data2,
363             dcerpc_uuid_program->Data3,
364             dcerpc_uuid_program->Data4[0], dcerpc_uuid_program->Data4[1],
365             dcerpc_uuid_program->Data4[2], dcerpc_uuid_program->Data4[3],
366             dcerpc_uuid_program->Data4[4], dcerpc_uuid_program->Data4[5],
367             dcerpc_uuid_program->Data4[6], dcerpc_uuid_program->Data4[7],
368             dcerpc_version, 0);
369         filter = gtk_entry_get_text(GTK_ENTRY(filter_entry));
370         if(filter[0] != 0){
371                 g_string_append_printf(str, ",%s", filter);
372         }
373
374         gtk_dcerpcstat_init(str->str,NULL);
375         g_string_free(str, TRUE);
376 }
377
378
379 static void
380 dcerpcstat_version_select(GtkWidget *vers_combo_box, gpointer user_data _U_)
381 {
382         dcerpc_uuid_key *k;
383
384         if (! ws_combo_box_get_active_pointer(GTK_COMBO_BOX(vers_combo_box), (gpointer *)&k)) {
385                 g_assert_not_reached();  /* Programming error: somehow no active item */
386         }
387
388         dcerpc_version = k->ver;
389 }
390
391 static void
392 dcerpcstat_find_vers(gpointer *key, gpointer *value _U_, gpointer user_data)
393 {
394         dcerpc_uuid_key *k = (dcerpc_uuid_key *)key;
395         GtkWidget       *vers_combo_box = (GtkWidget *)user_data;
396         char vs[5];
397
398         if(!uuid_equal(&(k->uuid), dcerpc_uuid_program)){
399                 return;
400         }
401         g_snprintf(vs, sizeof(vs), "%u", k->ver);
402         ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(vers_combo_box), vs, k);
403 }
404
405 static void
406 dcerpcstat_program_select(GtkWidget *prog_combo_box, gpointer user_data)
407 {
408         dcerpc_uuid_key *k;
409         GtkWidget *vers_combo_box;
410
411         vers_combo_box = (GtkWidget *)user_data;
412
413         if (! ws_combo_box_get_active_pointer(GTK_COMBO_BOX(prog_combo_box), (gpointer *)&k)) {
414                 g_assert_not_reached();  /* Programming error: somehow no active item */
415         }
416
417         g_signal_handlers_disconnect_by_func(vers_combo_box, G_CALLBACK(dcerpcstat_version_select), NULL );
418         ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(vers_combo_box));
419
420         /* dcerpc_stat: invalid selection... somehow selected top level ?? */
421         g_assert(k != NULL);
422         dcerpc_uuid_program = &(k->uuid);
423
424         /* re-create version menu */
425         g_signal_handlers_disconnect_by_func(vers_combo_box, G_CALLBACK(dcerpcstat_version_select), NULL );
426         ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(vers_combo_box));
427
428         g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, vers_combo_box);
429
430         g_signal_connect(vers_combo_box, "changed", G_CALLBACK(dcerpcstat_version_select), NULL);
431         ws_combo_box_set_active(GTK_COMBO_BOX(vers_combo_box), 0); /* default: triggers dcerpcstat_version_select callback */
432
433 }
434
435 static GtkTreeIter
436 dcerpcstat_add_program_to_menu(dcerpc_uuid_key *k, dcerpc_uuid_value *v, GtkWidget *prog_combo_box, int program_item_index)
437 {
438         static GtkTreeIter iter;
439         char str[64];
440
441         switch(program_item_index%15){
442         case 0:
443                 g_snprintf(str,sizeof(str),"%s ...",v->name);
444                 iter = ws_combo_box_append_text_and_pointer_full(
445                         GTK_COMBO_BOX(prog_combo_box), NULL, str, NULL, FALSE); /* top-level entries are insensitive */
446                 break;
447
448         default:
449                 break;
450         }
451
452         return ws_combo_box_append_text_and_pointer_full(
453                 GTK_COMBO_BOX(prog_combo_box), &iter, v->name, k, TRUE);
454 }
455
456 static void
457 dcerpcstat_find_next_program(gpointer *key, gpointer *value, gpointer *user_data _U_)
458 {
459         dcerpc_uuid_key   *k = (dcerpc_uuid_key *)key;
460         dcerpc_uuid_value *v = (dcerpc_uuid_value *)value;
461
462         /* first time called, just set new_uuid to this one */
463         if((current_uuid_key==NULL) && (new_uuid_key==NULL)){
464                 new_uuid_key   = k;
465                 new_uuid_value = v;
466                 return;
467         }
468
469         /* if we haven't got a current one yet, just check the new
470            and scan for the first one alphabetically  */
471         if(current_uuid_key==NULL){
472                 if(strcmp(new_uuid_value->name, v->name)>0){
473                         new_uuid_key   = k;
474                         new_uuid_value = v;
475                         return;
476                 }
477                 return;
478         }
479
480         /* searching for the next one we are only interested in those
481            that sorts alphabetically after the current one */
482         if(strcmp(current_uuid_value->name, v->name) >= 0){
483                 /* this one doesn't so just skip it */
484                 return;
485         }
486
487         /* is it the first potential new entry? */
488         if(new_uuid_key==NULL){
489                 new_uuid_key   = k;
490                 new_uuid_value = v;
491                 return;
492         }
493
494         /* does it sort before the current new one? */
495         if(strcmp(new_uuid_value->name, v->name) > 0){
496                 new_uuid_key   = k;
497                 new_uuid_value = v;
498                 return;
499         }
500
501         return;
502 }
503
504
505 static void
506 dlg_destroy_cb(GtkWidget *w _U_, gpointer user_data _U_)
507 {
508         dlg = NULL;
509 }
510
511
512 void gtk_dcerpcstat_cb(GtkAction *action _U_, gpointer user_data _U_)
513 {
514         GtkWidget       *dlg_box;
515         GtkWidget       *prog_box,   *prog_label, *prog_combo_box;
516         GtkWidget       *vers_label, *vers_combo_box;
517         GtkWidget       *filter_box, *filter_bt;
518         GtkWidget       *bbox, *start_button, *cancel_button;
519         GtkCellRenderer *cell_renderer;
520 #if 0
521         GtkTreeIter      program_first_item_iter;
522 #endif
523         const char      *filter;
524         int              program_item_index = 0;
525
526         static construct_args_t args = {
527           "Service Response Time Statistics Filter",
528           FALSE,
529           FALSE,
530           FALSE
531         };
532
533         /* if the window is already open, bring it to front and
534            un-minimize it, as necessary */
535         if(dlg){
536                 reactivate_window(dlg);
537                 return;
538         }
539
540         dlg = dlg_window_new("Wireshark: Compute DCE-RPC SRT statistics");
541         gtk_window_set_default_size(GTK_WINDOW(dlg), 400, -1);
542
543         dlg_box = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 10, FALSE);
544         gtk_container_set_border_width(GTK_CONTAINER(dlg_box), 10);
545         gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
546         gtk_widget_show(dlg_box);
547
548         /* Program box */
549         prog_box = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
550
551         /* Program label */
552         gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
553         prog_label = gtk_label_new("Program:");
554         gtk_box_pack_start(GTK_BOX(prog_box), prog_label, FALSE, FALSE, 0);
555         gtk_widget_show(prog_label);
556
557         /* Program menu */
558         dcerpc_uuid_program = NULL;   /* default: no program selected */
559
560         /* The "program combo box" is implemented with a two-level tree.
561            Each top-level of the tree has (up to) 15 selectable "program name"
562            children and shows the name of the first child of that entry
563            as "child_name ...". Each of the top-level entries can be expanded
564            (to show the children) but is "insensitive": ie: cannot be selected.
565            (dcerpcstat_add_program_to_menu() does the actual work to add entries
566             to the combo box).
567             XXX: A simpler alternative might be to just do away with all the two-level
568                  complexity and just use a standard ws_combo_box... even though the
569                  list of "program names" is quite large.
570             XXX: The gtkrc file distributed with Windows Wireshark has the
571                  "appears-as-list" GtkComboBox style property set to 1 and thus
572                  on Windows the entries for this combo box will appear as a tree-view.
573                  The default is 0(FALSE). In this case the the combo box entries will
574                  display as a menu with sub-menus.
575                  A possibility would be to set "appears-as-list" to 0  just for this
576                  particular combo box on Windows so that the entries will appear as a
577                  menu even on Windows).
578         */
579         prog_combo_box = ws_combo_box_new_text_and_pointer_full(&cell_renderer);
580         {
581                 /* XXX: Hack So that the top-level insensitive entries don't show
582                         as "grayed out"; The "foreground normal" color is used instead.
583                         This may not really be necessary but seems better to me.
584                 */
585 #if GTK_CHECK_VERSION(3,0,0)
586                 GtkStyleContext *context;
587                 GdkRGBA                 *new_rgba_fg_color;
588                 context = gtk_widget_get_style_context (prog_combo_box);
589                 gtk_style_context_get (context, GTK_STATE_FLAG_NORMAL,
590                                  "color", &new_rgba_fg_color,
591                                   NULL);
592
593                 g_object_set(cell_renderer,
594                              "foreground-rgba", &new_rgba_fg_color,
595                              "foreground-set", TRUE,
596                              NULL);
597
598 #else
599                 GtkStyle *s;
600                 s = gtk_widget_get_style(prog_combo_box);
601                 g_object_set(cell_renderer,
602                              "foreground-gdk", &(s->fg[GTK_STATE_NORMAL]),
603                              "foreground-set", TRUE,
604                              NULL);
605 #endif
606         }
607
608         current_uuid_key   = NULL;
609         current_uuid_value = NULL;
610         do {
611                 new_uuid_key   = NULL;
612                 new_uuid_value = NULL;
613                 g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_next_program, NULL);
614                 if(new_uuid_key){
615 #if 0
616                         GtkTreeIter tmp_iter;
617                         tmp_iter = dcerpcstat_add_program_to_menu(new_uuid_key, new_uuid_value,
618                                                                   prog_combo_box, program_item_index);
619                         if (program_item_index == 0)
620                                 program_first_item_iter = tmp_iter;
621 #else
622                         dcerpcstat_add_program_to_menu(new_uuid_key, new_uuid_value,
623                                                         prog_combo_box, program_item_index);
624 #endif
625                         program_item_index += 1;
626                 }
627                 current_uuid_key   = new_uuid_key;
628                 current_uuid_value = new_uuid_value;
629         } while(new_uuid_key != NULL);
630         gtk_box_pack_start(GTK_BOX(prog_box), prog_combo_box, TRUE, TRUE, 0);
631         gtk_widget_show(prog_combo_box);
632
633         /* Version label */
634         gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
635         vers_label = gtk_label_new("Version:");
636         gtk_box_pack_start(GTK_BOX(prog_box), vers_label, FALSE, FALSE, 0);
637         gtk_widget_show(vers_label);
638
639         /* Version combo-box */
640         /* Note: version combo box rows set when dcerpcstat_program_select() callback invoked */
641         vers_combo_box = ws_combo_box_new_text_and_pointer();
642         gtk_box_pack_start(GTK_BOX(prog_box), vers_combo_box, TRUE, TRUE, 0);
643         gtk_widget_show(vers_combo_box);
644
645         g_signal_connect(prog_combo_box, "changed", G_CALLBACK(dcerpcstat_program_select), vers_combo_box);
646 #if 0 /* Don't select an active entry given the way the drop down treeview appears if a default (active) entry is set */
647         ws_combo_box_set_active_iter(GTK_COMBO_BOX(prog_combo_box), &program_first_item_iter); /* triggers callback */
648 #endif
649         gtk_box_pack_start(GTK_BOX(dlg_box), prog_box, TRUE, TRUE, 0);
650         gtk_widget_show(prog_box);
651
652         /* Filter box */
653         filter_box = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3, FALSE);
654
655         /* Filter label */
656         filter_bt = ws_gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
657         g_signal_connect(filter_bt, "clicked", G_CALLBACK(display_filter_construct_cb), &args);
658         gtk_box_pack_start(GTK_BOX(filter_box), filter_bt, FALSE, FALSE, 0);
659         gtk_widget_show(filter_bt);
660
661         /* Filter entry */
662         filter_entry = gtk_entry_new();
663         g_signal_connect(filter_entry, "changed", G_CALLBACK(filter_te_syntax_check_cb), NULL);
664         g_object_set_data(G_OBJECT(filter_box), E_FILT_AUTOCOMP_PTR_KEY, NULL);
665         g_signal_connect(filter_entry, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
666         g_signal_connect(dlg, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
667         gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
668         filter = gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
669         if(filter){
670                 gtk_entry_set_text(GTK_ENTRY(filter_entry), filter);
671         } else {
672                 colorize_filter_te_as_empty(filter_entry);
673         }
674         gtk_widget_show(filter_entry);
675
676         gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
677         gtk_widget_show(filter_box);
678
679         g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_entry);
680
681         /* button box */
682         bbox = dlg_button_row_new(WIRESHARK_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
683         gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
684         gtk_widget_show(bbox);
685
686         start_button = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CREATE_STAT);
687         g_signal_connect_swapped(start_button, "clicked",
688                                  G_CALLBACK(dcerpcstat_start_button_clicked), NULL);
689
690         cancel_button = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
691         window_set_cancel_button(dlg, cancel_button, window_cancel_button_cb);
692
693         g_signal_connect(dlg, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
694         g_signal_connect(dlg, "destroy", G_CALLBACK(dlg_destroy_cb), NULL);
695
696         /* Catch the "activate" signal on the filter text entry, so that
697            if the user types Return there, we act as if the "Create Stat"
698            button had been selected, as happens if Return is typed if some
699            widget that *doesn't* handle the Return key has the input
700            focus. */
701         dlg_set_activate(filter_entry, start_button);
702
703         gtk_widget_grab_default(start_button );
704
705         /* Give the initial focus to the "Filter" entry box. */
706         gtk_widget_grab_focus(filter_entry);
707
708         gtk_widget_show_all(dlg);
709         window_present(dlg);
710 }
711
712 static stat_tap_ui dcerpcstat_ui = {
713         REGISTER_STAT_GROUP_GENERIC,
714         NULL,
715         "dcerpc,srt",
716         gtk_dcerpcstat_init,
717         -1,
718         0,
719         NULL
720 };
721
722 void
723 register_tap_listener_gtkdcerpcstat(void)
724 {
725         register_stat_tap_ui(&dcerpcstat_ui, NULL);
726 }