removed unused #include "menu.h" from the stats.c files
[obnox/wireshark/wip.git] / gtk / dcerpc_stat.c
1 /* dcerpc_stat.c
2  * dcerpc_stat   2002 Ronnie Sahlberg
3  *
4  * $Id: dcerpc_stat.c,v 1.32 2003/12/13 17:10:21 ulfl Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  * 
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 /* This module provides rpc call/reply SRT statistics to ethereal,
26  * and displays them graphically.
27  * It is only used by ethereal and not tethereal
28  *
29  * It serves as an example on how to use the tap api.
30  */
31
32 #ifdef HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <string.h>
37 #include <gtk/gtk.h>
38 #include "epan/packet_info.h"
39 #include "epan/epan.h"
40 #include "simple_dialog.h"
41 #include "dlg_utils.h"
42 #include "ui_util.h"
43 #include "tap.h"
44 #include "../register.h"
45 #include "packet-dcerpc.h"
46 #include "../globals.h"
47 #include "filter_prefs.h"
48 #include "compat_macros.h"
49 #include "service_response_time_table.h"
50
51
52 extern GtkWidget   *main_display_filter_widget;
53
54 /* used to keep track of the statistics for an entire program interface */
55 typedef struct _rpcstat_t {
56         GtkWidget *win;
57         srt_stat_table srt_table;
58         char *prog;
59         e_uuid_t uuid;
60         guint16 ver;
61         int num_procedures;
62 } rpcstat_t;
63
64
65 static int
66 uuid_equal(e_uuid_t *uuid1, e_uuid_t *uuid2)
67 {
68         if( (uuid1->Data1!=uuid2->Data1)
69           ||(uuid1->Data2!=uuid2->Data2)
70           ||(uuid1->Data3!=uuid2->Data3)
71           ||(uuid1->Data4[0]!=uuid2->Data4[0])
72           ||(uuid1->Data4[1]!=uuid2->Data4[1])
73           ||(uuid1->Data4[2]!=uuid2->Data4[2])
74           ||(uuid1->Data4[3]!=uuid2->Data4[3])
75           ||(uuid1->Data4[4]!=uuid2->Data4[4])
76           ||(uuid1->Data4[5]!=uuid2->Data4[5])
77           ||(uuid1->Data4[6]!=uuid2->Data4[6])
78           ||(uuid1->Data4[7]!=uuid2->Data4[7]) ){
79                 return 0;
80         }
81         return 1;
82 }
83
84 static char *
85 dcerpcstat_gen_title(rpcstat_t *rs)
86 {
87         char *title;
88
89         title = g_strdup_printf("DCE-RPC Service Response Time statistics for %s version %d.%d: %s", rs->prog, rs->ver&0xff, rs->ver>>8, cf_get_display_name(&cfile));
90         return title;
91 }
92
93 static void
94 dcerpcstat_set_title(rpcstat_t *rs)
95 {
96         char *title;
97
98         title = dcerpcstat_gen_title(rs);
99         gtk_window_set_title(GTK_WINDOW(rs->win), title);
100         g_free(title);
101 }
102
103 static void
104 dcerpcstat_reset(rpcstat_t *rs)
105 {
106         reset_srt_table_data(&rs->srt_table);
107         dcerpcstat_set_title(rs);
108 }
109
110
111 static int
112 dcerpcstat_packet(rpcstat_t *rs, packet_info *pinfo, epan_dissect_t *edt _U_, dcerpc_info *ri)
113 {
114         if(!ri->call_data){
115                 return 0;
116         }
117         if(!ri->call_data->req_frame){
118                 /* we have not seen the request so we dont know the delta*/
119                 return 0;
120         }
121         if(ri->call_data->opnum>=rs->num_procedures){
122                 /* dont handle this since its outside of known table */
123                 return 0;
124         }
125
126         /* we are only interested in reply packets */
127         if(ri->request){
128                 return 0;
129         }
130
131         /* we are only interested in certain program/versions */
132         if( (!uuid_equal( (&ri->call_data->uuid), (&rs->uuid)))
133           ||(ri->call_data->ver!=rs->ver)){
134                 return 0;
135         }
136
137
138         add_srt_table_data(&rs->srt_table, ri->call_data->opnum, &ri->call_data->req_time, pinfo);
139
140
141         return 1;
142 }
143
144 static void
145 dcerpcstat_draw(rpcstat_t *rs)
146 {
147         draw_srt_table_data(&rs->srt_table);
148 }
149
150
151 /* since the gtk2 implementation of tap is multithreaded we must protect
152  * remove_tap_listener() from modifying the list while draw_tap_listener()
153  * is running.  the other protected block is in main.c
154  *
155  * there should not be any other critical regions in gtk2
156  */
157 void protect_thread_critical_region(void);
158 void unprotect_thread_critical_region(void);
159 static void
160 win_destroy_cb(GtkWindow *win _U_, gpointer data)
161 {
162         rpcstat_t *rs=(rpcstat_t *)data;
163
164         protect_thread_critical_region();
165         remove_tap_listener(rs);
166         unprotect_thread_critical_region();
167
168         free_srt_table_data(&rs->srt_table);
169         g_free(rs);
170 }
171
172
173
174 /* When called, this function will create a new instance of gtk-dcerpcstat.
175  */
176 static void
177 gtk_dcerpcstat_init(char *optarg)
178 {
179         rpcstat_t *rs;
180         guint32 i, max_procs;
181         char *title_string;
182         char filter_string[256];
183         GtkWidget *vbox;
184         GtkWidget *stat_label;
185         GtkWidget *filter_label;
186         dcerpc_sub_dissector *procs;
187         e_uuid_t uuid;
188         int d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
189         int major, minor;
190         int pos=0;
191         char *filter=NULL;
192         GString *error_string;
193         int hf_opnum;
194
195         if(sscanf(optarg,"dcerpc,srt,%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d,%n", &d1,&d2,&d3,&d40,&d41,&d42,&d43,&d44,&d45,&d46,&d47,&major,&minor,&pos)==13){
196                 uuid.Data1=d1;
197                 uuid.Data2=d2;
198                 uuid.Data3=d3;
199                 uuid.Data4[0]=d40;
200                 uuid.Data4[1]=d41;
201                 uuid.Data4[2]=d42;
202                 uuid.Data4[3]=d43;
203                 uuid.Data4[4]=d44;
204                 uuid.Data4[5]=d45;
205                 uuid.Data4[6]=d46;
206                 uuid.Data4[7]=d47;
207                 if(pos){
208                         filter=optarg+pos;
209                 } else {
210                         filter=NULL;
211                 }
212         } else {
213                 fprintf(stderr, "ethereal: invalid \"-z dcerpc,srt,<uuid>,<major version>.<minor version>[,<filter>]\" argument\n");
214                 exit(1);
215         }
216
217
218         rs=g_malloc(sizeof(rpcstat_t));
219         if (major < 0 || major > 255 || minor < 0 || minor > 255)
220                 rs->prog = NULL;        /* bogus major or minor */
221         else
222                 rs->prog=dcerpc_get_proto_name(&uuid, (guint16) ((minor<<8)|(major&0xff)) );
223         if(!rs->prog){
224                 g_free(rs);
225                 fprintf(stderr,"ethereal: dcerpcstat_init() Protocol with uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x v%d.%d not supported\n",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],major,minor);
226                 exit(1);
227         }
228         hf_opnum=dcerpc_get_proto_hf_opnum(&uuid, (guint16) ((minor<<8)|(major&0xff)) );
229         procs=dcerpc_get_proto_sub_dissector(&uuid, (guint16) ((minor<<8)|(major&0xff)) );
230         rs->uuid=uuid;
231         rs->ver=(minor<<8)|(major&0xff);
232
233         rs->win=gtk_window_new(GTK_WINDOW_TOPLEVEL);
234         gtk_window_set_default_size(GTK_WINDOW(rs->win), 550, 400);
235         dcerpcstat_set_title(rs);
236         SIGNAL_CONNECT(rs->win, "destroy", win_destroy_cb, rs);
237
238         vbox=gtk_vbox_new(FALSE, 0);
239         gtk_container_add(GTK_CONTAINER(rs->win), vbox);
240         gtk_container_set_border_width(GTK_CONTAINER(vbox), 10);
241         gtk_widget_show(vbox);
242
243         title_string=dcerpcstat_gen_title(rs);
244         stat_label=gtk_label_new(title_string);
245         g_free(title_string);
246         gtk_box_pack_start(GTK_BOX(vbox), stat_label, FALSE, FALSE, 0);
247         gtk_widget_show(stat_label);
248
249         snprintf(filter_string,255,"Filter:%s",filter?filter:"");
250         filter_label=gtk_label_new(filter_string);
251         gtk_box_pack_start(GTK_BOX(vbox), filter_label, FALSE, FALSE, 0);
252         gtk_widget_show(filter_label);
253
254         for(i=0,max_procs=0;procs[i].name;i++){
255                 if(procs[i].num>max_procs){
256                         max_procs=procs[i].num;
257                 }
258         }
259         rs->num_procedures=max_procs+1;
260
261         /* We must display TOP LEVEL Widget before calling init_srt_table() */
262         gtk_widget_show(rs->win);
263
264         if(hf_opnum!=-1){
265                 init_srt_table(&rs->srt_table, max_procs+1, vbox, proto_registrar_get_nth(hf_opnum)->abbrev);
266         } else {
267                 init_srt_table(&rs->srt_table, max_procs+1, vbox, NULL);
268         }
269
270         for(i=0;i<(max_procs+1);i++){
271                 int j;
272                 char *proc_name;
273
274                 proc_name="unknown";
275                 for(j=0;procs[j].name;j++){
276                         if(procs[j].num==i){
277                                 proc_name=procs[j].name;
278                         }
279                 }
280
281                 init_srt_table_row(&rs->srt_table, i, proc_name);
282         }
283
284
285         error_string=register_tap_listener("dcerpc", rs, filter, (void*)dcerpcstat_reset, (void*)dcerpcstat_packet, (void*)dcerpcstat_draw);
286         if(error_string){
287                 /* error, we failed to attach to the tap. clean up */
288                 simple_dialog(ESD_TYPE_WARN, NULL, error_string->str);
289                 g_string_free(error_string, TRUE);
290                 free_srt_table_data(&rs->srt_table);
291                 g_free(rs);
292                 return;
293         }
294
295
296         gtk_widget_show_all(rs->win);
297         redissect_packets(&cfile);
298 }
299
300
301
302 static e_uuid_t *dcerpc_uuid_program=NULL;
303 static guint16 dcerpc_version;
304 static GtkWidget *dlg=NULL;
305 static GtkWidget *prog_menu;
306 static GtkWidget *vers_opt, *vers_menu;
307 static GtkWidget *filter_entry;
308 static dcerpc_uuid_key *current_uuid_key=NULL;
309 static dcerpc_uuid_value *current_uuid_value=NULL;
310 static dcerpc_uuid_key *new_uuid_key=NULL;
311 static dcerpc_uuid_value *new_uuid_value=NULL;
312
313
314 static void
315 dcerpcstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
316 {
317         GString *str;
318         char *filter;
319
320         str = g_string_new("dcerpc,srt");
321         g_string_sprintfa(str,
322             ",%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%d.%d",
323             dcerpc_uuid_program->Data1, dcerpc_uuid_program->Data2,
324             dcerpc_uuid_program->Data3,
325             dcerpc_uuid_program->Data4[0], dcerpc_uuid_program->Data4[1],
326             dcerpc_uuid_program->Data4[2], dcerpc_uuid_program->Data4[3],
327             dcerpc_uuid_program->Data4[4], dcerpc_uuid_program->Data4[5],
328             dcerpc_uuid_program->Data4[6], dcerpc_uuid_program->Data4[7],
329             dcerpc_version&0xff, dcerpc_version>>8);
330         filter=(char *)gtk_entry_get_text(GTK_ENTRY(filter_entry));
331         if(filter[0]!=0){
332                 g_string_sprintfa(str, ",%s", filter);
333         }
334
335         gtk_dcerpcstat_init(str->str);
336         g_string_free(str, TRUE);
337 }
338
339
340 static void
341 dcerpcstat_version_select(GtkWidget *item _U_, gpointer key)
342 {
343         int vers=(int)key;
344
345         dcerpc_version=vers;
346 }
347
348
349
350
351 static void *
352 dcerpcstat_find_vers(gpointer *key, gpointer *value _U_, gpointer *user_data _U_)
353 {
354         dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
355         GtkWidget *menu_item;
356         char vs[5];
357
358         if(!uuid_equal((&k->uuid), dcerpc_uuid_program)){
359                 return NULL;
360         }
361
362         sprintf(vs,"%d.%d",k->ver&0xff,k->ver>>8);
363         menu_item=gtk_menu_item_new_with_label(vs);
364         SIGNAL_CONNECT(menu_item, "activate", dcerpcstat_version_select,
365                        ((int)k->ver));
366         gtk_widget_show(menu_item);
367         gtk_menu_append(GTK_MENU(vers_menu), menu_item);
368
369         if(dcerpc_version==0xffff){
370                 dcerpc_version=k->ver;
371         }
372
373         return NULL;
374 }
375
376
377 static void
378 dcerpcstat_program_select(GtkWidget *item _U_, gpointer key)
379 {
380         dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
381
382         dcerpc_uuid_program=&k->uuid;
383
384         /* change version menu */
385         dcerpc_version=0xffff;
386         gtk_object_destroy(GTK_OBJECT(vers_menu));
387         vers_menu=gtk_menu_new();
388         g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
389         gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
390 }
391
392
393 static GtkWidget *program_submenu_menu;
394 static GtkWidget *program_submenu_item;
395 static GtkWidget *program_submenu_label;
396 static int program_subitem_index;
397 static char *first_menu_name;
398 static void 
399 dcerpcstat_add_program_to_menu(dcerpc_uuid_key *k, dcerpc_uuid_value *v)
400 {
401         GtkWidget *program_menu_item;
402         GtkWidget *box;
403         char str[64];
404
405         switch(program_subitem_index%15){
406         case 0:
407
408                 first_menu_name=v->name;
409                 snprintf(str,63,"%s ...",v->name);
410                 program_submenu_item=gtk_menu_item_new();
411                 box=gtk_hbox_new(TRUE,0);
412                 gtk_container_add(GTK_CONTAINER(program_submenu_item), box);
413                 
414                 program_submenu_label=gtk_label_new(str);
415                 gtk_box_pack_start(GTK_BOX(box), program_submenu_label, TRUE, TRUE, 0);
416                 gtk_widget_show(program_submenu_label);
417                 gtk_widget_show(box);
418
419                 gtk_menu_append(GTK_MENU(prog_menu), program_submenu_item);
420                 gtk_widget_show(program_submenu_item);
421
422                 program_submenu_menu=gtk_menu_new();
423                 gtk_menu_item_set_submenu(GTK_MENU_ITEM(program_submenu_item), program_submenu_menu);
424                 break;
425         case 14:
426                 snprintf(str,63,"%s - %s",first_menu_name,v->name);
427                 gtk_label_set_text(GTK_LABEL(program_submenu_label), str);
428                 break;
429 /*qqq*/
430         }
431         program_subitem_index++;                
432
433         program_menu_item=gtk_menu_item_new_with_label(v->name);
434         SIGNAL_CONNECT(program_menu_item, "activate", dcerpcstat_program_select, k);
435
436         gtk_widget_show(program_menu_item);
437         gtk_menu_append(GTK_MENU(program_submenu_menu), program_menu_item);
438
439         if(!dcerpc_uuid_program){
440                 dcerpc_uuid_program=&k->uuid;
441         }
442
443         return;
444 }
445
446 static void *
447 dcerpcstat_find_next_program(gpointer *key, gpointer *value, gpointer *user_data _U_)
448 {
449         dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
450         dcerpc_uuid_value *v=(dcerpc_uuid_value *)value;
451
452         /* first time called, just set new_uuid to this one */
453         if((current_uuid_key==NULL)&&(new_uuid_key==NULL)){
454                 new_uuid_key=k;
455                 new_uuid_value=v;
456                 return NULL;
457         }
458
459         /* if we havent got a current one yet, just check the new
460            and scan for the first one alphabetically  */
461         if(current_uuid_key==NULL){
462                 if(strcmp(new_uuid_value->name, v->name)>0){
463                         new_uuid_key=k;
464                         new_uuid_value=v;
465                         return NULL;
466                 }
467                 return NULL;
468         }
469
470         /* searching for the next one we are only interested in those
471            that sorts alphabetically after the current one */
472         if(strcmp(current_uuid_value->name, v->name)>=0){
473                 /* this one doesnt so just skip it */
474                 return NULL;
475         }
476
477         /* is it the first potential new entry? */
478         if(new_uuid_key==NULL){
479                 new_uuid_key=k;
480                 new_uuid_value=v;
481                 return NULL;
482         }
483
484         /* does it sort before the current new one? */
485         if(strcmp(new_uuid_value->name, v->name)>0){
486                 new_uuid_key=k;
487                 new_uuid_value=v;
488                 return NULL;
489         }
490
491         return NULL;
492 }
493
494
495 static void
496 dlg_destroy_cb(void)
497 {
498         dlg=NULL;
499 }
500
501
502 static void
503 dlg_cancel_cb(GtkWidget *cancel_bt _U_, gpointer parent_w)
504 {
505         gtk_widget_destroy(GTK_WIDGET(parent_w));
506 }
507
508
509 static void
510 gtk_dcerpcstat_cb(GtkWidget *w _U_, gpointer d _U_)
511 {
512         GtkWidget *dlg_box;
513         GtkWidget *prog_box, *prog_label, *prog_opt;
514         GtkWidget *vers_label;
515         GtkWidget *filter_box, *filter_bt;
516         GtkWidget *bbox, *start_button, *cancel_button;
517         const char *filter;
518         static construct_args_t args = {
519           "Service Response Time Statistics Filter",
520           TRUE,
521           FALSE
522         };
523
524         /* if the window is already open, bring it to front and
525            un-minimize it, as necessary */
526         if(dlg){
527                 reactivate_window(dlg);
528                 return;
529         }
530
531         dlg=dlg_window_new("Ethereal: Compute DCE-RPC SRT statistics");
532         SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
533
534         dlg_box=gtk_vbox_new(FALSE, 10);
535         gtk_container_border_width(GTK_CONTAINER(dlg_box), 10);
536         gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
537         gtk_widget_show(dlg_box);
538
539         /* Program box */
540         prog_box=gtk_hbox_new(FALSE, 3);
541
542         /* Program label */
543         gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
544         prog_label=gtk_label_new("Program:");
545         gtk_box_pack_start(GTK_BOX(prog_box), prog_label, FALSE, FALSE, 0);
546         gtk_widget_show(prog_label);
547
548         /* Program menu */
549         prog_opt=gtk_option_menu_new();
550         prog_menu=gtk_menu_new();
551         current_uuid_key=NULL;
552         current_uuid_value=NULL;
553 /*qqq*/
554         program_submenu_item=NULL;
555         program_submenu_menu=NULL;
556         program_subitem_index=0;
557         do {
558                 new_uuid_key=NULL;
559                 new_uuid_value=NULL;
560                 g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_next_program, NULL);
561                 if(new_uuid_key){
562                         dcerpcstat_add_program_to_menu(new_uuid_key, new_uuid_value);
563                 }
564                 current_uuid_key=new_uuid_key;
565                 current_uuid_value=new_uuid_value;
566         } while(new_uuid_key!=NULL);
567
568         gtk_option_menu_set_menu(GTK_OPTION_MENU(prog_opt), prog_menu);
569         gtk_box_pack_start(GTK_BOX(prog_box), prog_opt, TRUE, TRUE, 0);
570         gtk_widget_show(prog_opt);
571
572         /* Version label */
573         gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
574         vers_label=gtk_label_new("Version:");
575         gtk_box_pack_start(GTK_BOX(prog_box), vers_label, FALSE, FALSE, 0);
576         gtk_widget_show(vers_label);
577
578         /* Version menu */
579         vers_opt=gtk_option_menu_new();
580         vers_menu=gtk_menu_new();
581         dcerpc_version=0xffff;
582         g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
583         gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
584         gtk_box_pack_start(GTK_BOX(prog_box), vers_opt, TRUE, TRUE, 0);
585         gtk_widget_show(vers_opt);
586
587         gtk_box_pack_start(GTK_BOX(dlg_box), prog_box, TRUE, TRUE, 0);
588         gtk_widget_show(prog_box);
589
590         /* Filter box */
591         filter_box=gtk_hbox_new(FALSE, 3);
592
593         /* Filter label */
594         filter_bt=gtk_button_new_with_label("Filter:");
595         SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
596         gtk_box_pack_start(GTK_BOX(filter_box), filter_bt, FALSE, FALSE, 0);
597         gtk_widget_show(filter_bt);
598
599         /* Filter entry */
600         filter_entry=gtk_entry_new();
601         gtk_widget_set_usize(filter_entry, 300, -2);
602
603         /* Filter entry */
604         filter_entry=gtk_entry_new();
605         gtk_widget_set_usize(filter_entry, 300, -2);
606
607         gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
608         filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
609         if(filter){
610                 gtk_entry_set_text(GTK_ENTRY(filter_entry), filter);
611         }
612         gtk_widget_show(filter_entry);
613         
614         gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
615         gtk_widget_show(filter_box);
616
617         /* button box */
618         bbox=gtk_hbutton_box_new();
619         gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_DEFAULT_STYLE);
620         gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
621         gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
622         gtk_widget_show(bbox);
623
624         /* the start button */
625         start_button=gtk_button_new_with_label("Create Stat");
626         SIGNAL_CONNECT_OBJECT(start_button, "clicked", 
627                               dcerpcstat_start_button_clicked, NULL);
628         gtk_box_pack_start(GTK_BOX(bbox), start_button, TRUE, TRUE, 0);
629         GTK_WIDGET_SET_FLAGS(start_button, GTK_CAN_DEFAULT);
630         gtk_widget_grab_default(start_button);
631         gtk_widget_show(start_button);
632
633 #if GTK_MAJOR_VERSION < 2
634         cancel_button=gtk_button_new_with_label("Cancel");
635 #else
636         cancel_button=gtk_button_new_from_stock(GTK_STOCK_CANCEL);
637 #endif
638         SIGNAL_CONNECT(cancel_button, "clicked", dlg_cancel_cb, dlg);
639         GTK_WIDGET_SET_FLAGS(cancel_button, GTK_CAN_DEFAULT);
640         gtk_box_pack_start(GTK_BOX(bbox), cancel_button, TRUE, TRUE, 0);
641         gtk_widget_show(cancel_button);
642
643         /* Catch the "activate" signal on the filter text entry, so that
644            if the user types Return there, we act as if the "Create Stat"
645            button had been selected, as happens if Return is typed if some
646            widget that *doesn't* handle the Return key has the input
647            focus. */
648         dlg_set_activate(filter_entry, start_button);
649
650         /* Catch the "key_press_event" signal in the window, so that we can
651            catch the ESC key being pressed and act as if the "Cancel" button
652            had been selected. */
653         dlg_set_cancel(dlg, cancel_button);
654
655         /* Give the initial focus to the "Filter" entry box. */
656         gtk_widget_grab_focus(filter_entry);
657
658         gtk_widget_show_all(dlg);
659 }
660
661 void
662 register_tap_listener_gtkdcerpcstat(void)
663 {
664         register_ethereal_tap("dcerpc,srt,", gtk_dcerpcstat_init);
665 }
666
667 void
668 register_tap_menu_gtkdcerpcstat(void)
669 {
670         register_tap_menu_item("Statistics/Service Response Time/DCE-RPC...",
671             gtk_dcerpcstat_cb, NULL, NULL);
672 }