OBJECT_..._DATA --> g_object_..._data
[obnox/wireshark/wip.git] / gtk / dcerpc_stat.c
1 /* dcerpc_stat.c
2  * dcerpc_stat   2002 Ronnie Sahlberg
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
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 Wireshark,
26  * and displays them graphically.
27  * It is only used by Wireshark and not tshark
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
38 #include <gtk/gtk.h>
39 #include <glib.h>
40
41 #include <epan/packet_info.h>
42 #include <epan/epan.h>
43
44 #include <epan/stat_cmd_args.h>
45 #include "../stat_menu.h"
46 #include "gui_stat_menu.h"
47 #include "simple_dialog.h"
48 #include "dlg_utils.h"
49 #include "gui_utils.h"
50 #include <epan/tap.h>
51 #include "../register.h"
52 #include <epan/dissectors/packet-dcerpc.h>
53 #include "../globals.h"
54 #include "filter_dlg.h"
55 #include "compat_macros.h"
56 #include "service_response_time_table.h"
57 #include "gtkglobals.h"
58
59
60 /* used to keep track of the statistics for an entire program interface */
61 typedef struct _rpcstat_t {
62         GtkWidget *win;
63         srt_stat_table srt_table;
64         const char *prog;
65         e_uuid_t uuid;
66         guint16 ver;
67         int num_procedures;
68 } rpcstat_t;
69
70
71 static int
72 uuid_equal(e_uuid_t *uuid1, e_uuid_t *uuid2)
73 {
74         if( (uuid1->Data1!=uuid2->Data1)
75           ||(uuid1->Data2!=uuid2->Data2)
76           ||(uuid1->Data3!=uuid2->Data3)
77           ||(uuid1->Data4[0]!=uuid2->Data4[0])
78           ||(uuid1->Data4[1]!=uuid2->Data4[1])
79           ||(uuid1->Data4[2]!=uuid2->Data4[2])
80           ||(uuid1->Data4[3]!=uuid2->Data4[3])
81           ||(uuid1->Data4[4]!=uuid2->Data4[4])
82           ||(uuid1->Data4[5]!=uuid2->Data4[5])
83           ||(uuid1->Data4[6]!=uuid2->Data4[6])
84           ||(uuid1->Data4[7]!=uuid2->Data4[7]) ){
85                 return 0;
86         }
87         return 1;
88 }
89
90 static char *
91 dcerpcstat_gen_title(rpcstat_t *rs)
92 {
93         char *title;
94
95         title = g_strdup_printf("DCE-RPC Service Response Time statistics for %s major version %u: %s", rs->prog, rs->ver, cf_get_display_name(&cfile));
96         return title;
97 }
98
99 static void
100 dcerpcstat_set_title(rpcstat_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         rpcstat_t *rs = rs_arg;
113
114         reset_srt_table_data(&rs->srt_table);
115         dcerpcstat_set_title(rs);
116 }
117
118
119 static int
120 dcerpcstat_packet(void *rs_arg, packet_info *pinfo, epan_dissect_t *edt _U_, const void *ri_arg)
121 {
122         rpcstat_t *rs = rs_arg;
123         const dcerpc_info *ri = ri_arg;
124
125         if(!ri->call_data){
126                 return 0;
127         }
128         if(!ri->call_data->req_frame){
129                 /* we have not seen the request so we dont know the delta*/
130                 return 0;
131         }
132         if(ri->call_data->opnum>=rs->num_procedures){
133                 /* dont handle this since its outside of known table */
134                 return 0;
135         }
136
137         /* we are only interested in reply packets */
138         if(ri->ptype != PDU_RESP){
139                 return 0;
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 0;
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 1;
153 }
154
155 static void
156 dcerpcstat_draw(void *rs_arg)
157 {
158         rpcstat_t *rs = rs_arg;
159
160         draw_srt_table_data(&rs->srt_table);
161 }
162
163
164 /* since the gtk2 implementation of tap is multithreaded we must protect
165  * remove_tap_listener() from modifying the list while draw_tap_listener()
166  * is running.  the other protected block is in main.c
167  *
168  * there should not be any other critical regions in gtk2
169  */
170 void protect_thread_critical_region(void);
171 void unprotect_thread_critical_region(void);
172 static void
173 win_destroy_cb(GtkWindow *win _U_, gpointer data)
174 {
175         rpcstat_t *rs=(rpcstat_t *)data;
176
177         protect_thread_critical_region();
178         remove_tap_listener(rs);
179         unprotect_thread_critical_region();
180
181         free_srt_table_data(&rs->srt_table);
182         g_free(rs);
183 }
184
185
186
187 /* When called, this function will create a new instance of gtk-dcerpcstat.
188  */
189 static void
190 gtk_dcerpcstat_init(const char *optarg, void* userdata _U_)
191 {
192         rpcstat_t *rs;
193         guint32 i, max_procs;
194         char *title_string;
195         char *filter_string;
196         GtkWidget *vbox;
197         GtkWidget *stat_label;
198         GtkWidget *filter_label;
199         GtkWidget *bbox;
200         GtkWidget *close_bt;
201         dcerpc_sub_dissector *procs;
202         e_uuid_t uuid;
203         guint d1,d2,d3,d40,d41,d42,d43,d44,d45,d46,d47;
204         int major, minor;
205         guint16 ver;
206         int pos=0;
207         const char *filter=NULL;
208         GString *error_string;
209         int hf_opnum;
210
211         /*
212          * XXX - DCE RPC statistics are maintained only by major version,
213          * not by major and minor version, so the minor version number is
214          * ignored.
215          *
216          * Should we just stop supporting minor version numbers here?
217          * Or should we allow it to be omitted?  Or should we keep
218          * separate statistics for different minor version numbers,
219          * and allow the minor version number to be omitted, and
220          * report aggregate statistics for all minor version numbers
221          * if it's omitted?
222          */
223         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){
224                 uuid.Data1=d1;
225                 uuid.Data2=d2;
226                 uuid.Data3=d3;
227                 uuid.Data4[0]=d40;
228                 uuid.Data4[1]=d41;
229                 uuid.Data4[2]=d42;
230                 uuid.Data4[3]=d43;
231                 uuid.Data4[4]=d44;
232                 uuid.Data4[5]=d45;
233                 uuid.Data4[6]=d46;
234                 uuid.Data4[7]=d47;
235                 if(pos){
236                         filter=optarg+pos;
237                 } else {
238                         filter=NULL;
239                 }
240         } else {
241                 fprintf(stderr, "wireshark: invalid \"-z dcerpc,srt,<uuid>,<major version>.<minor version>[,<filter>]\" argument\n");
242                 exit(1);
243         }
244         if (major < 0 || major > 65535) {
245                 fprintf(stderr,"wireshark: dcerpcstat_init() Major version number %d is invalid - must be positive and <= 65535\n", major);
246                 exit(1);
247         }
248         if (minor < 0 || minor > 65535) {
249                 fprintf(stderr,"wireshark: dcerpcstat_init() Minor version number %d is invalid - must be positive and <= 65535\n", minor);
250                 exit(1);
251         }
252         ver = major;
253
254         rs=g_malloc(sizeof(rpcstat_t));
255         rs->prog=dcerpc_get_proto_name(&uuid, ver);
256         if(!rs->prog){
257                 g_free(rs);
258                 fprintf(stderr,"wireshark: dcerpcstat_init() Protocol with uuid:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x v%u 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],ver);
259                 exit(1);
260         }
261         hf_opnum=dcerpc_get_proto_hf_opnum(&uuid, ver);
262         procs=dcerpc_get_proto_sub_dissector(&uuid, ver);
263         rs->uuid=uuid;
264         rs->ver=ver;
265
266         rs->win=window_new(GTK_WINDOW_TOPLEVEL, "dcerpc-stat");
267         dcerpcstat_set_title(rs);
268         gtk_window_set_default_size(GTK_WINDOW(rs->win), 550, 400);
269
270         vbox=gtk_vbox_new(FALSE, 3);
271         gtk_container_add(GTK_CONTAINER(rs->win), vbox);
272         gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
273
274         title_string=dcerpcstat_gen_title(rs);
275         stat_label=gtk_label_new(title_string);
276         g_free(title_string);
277         gtk_box_pack_start(GTK_BOX(vbox), stat_label, FALSE, FALSE, 0);
278
279         filter_string = g_strdup_printf("Filter: %s",filter ? filter : "");
280         filter_label=gtk_label_new(filter_string);
281         g_free(filter_string);
282         gtk_label_set_line_wrap(GTK_LABEL(filter_label), TRUE);
283         gtk_box_pack_start(GTK_BOX(vbox), filter_label, FALSE, FALSE, 0);
284
285         for(i=0,max_procs=0;procs[i].name;i++){
286                 if(procs[i].num>max_procs){
287                         max_procs=procs[i].num;
288                 }
289         }
290         rs->num_procedures=max_procs+1;
291
292         /* We must display TOP LEVEL Widget before calling init_srt_table() */
293         gtk_widget_show_all(rs->win);
294
295         if(hf_opnum!=-1){
296                 init_srt_table(&rs->srt_table, max_procs+1, vbox, proto_registrar_get_nth(hf_opnum)->abbrev);
297         } else {
298                 init_srt_table(&rs->srt_table, max_procs+1, vbox, NULL);
299         }
300
301         for(i=0;i<(max_procs+1);i++){
302                 int j;
303                 const char *proc_name;
304
305                 proc_name="unknown";
306                 for(j=0;procs[j].name;j++){
307                         if(procs[j].num==i){
308                                 proc_name=procs[j].name;
309                         }
310                 }
311
312                 init_srt_table_row(&rs->srt_table, i, proc_name);
313         }
314
315
316         error_string=register_tap_listener("dcerpc", rs, filter, dcerpcstat_reset, dcerpcstat_packet, dcerpcstat_draw);
317         if(error_string){
318                 /* error, we failed to attach to the tap. clean up */
319                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
320                 g_string_free(error_string, TRUE);
321                 free_srt_table_data(&rs->srt_table);
322                 g_free(rs);
323                 return;
324         }
325
326         /* Button row. */
327         bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
328         gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
329
330         close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
331         window_set_cancel_button(rs->win, close_bt, window_cancel_button_cb);
332
333         SIGNAL_CONNECT(rs->win, "delete_event", window_delete_event_cb, NULL);
334         SIGNAL_CONNECT(rs->win, "destroy", win_destroy_cb, rs);
335
336         gtk_widget_show_all(rs->win);
337         window_present(rs->win);
338
339         cf_retap_packets(&cfile, FALSE);
340 }
341
342
343
344 static e_uuid_t *dcerpc_uuid_program=NULL;
345 static guint16 dcerpc_version;
346 static GtkWidget *dlg=NULL;
347 static GtkWidget *prog_menu;
348 static GtkWidget *vers_opt, *vers_menu;
349 static GtkWidget *filter_entry;
350 static dcerpc_uuid_key *current_uuid_key=NULL;
351 static dcerpc_uuid_value *current_uuid_value=NULL;
352 static dcerpc_uuid_key *new_uuid_key=NULL;
353 static dcerpc_uuid_value *new_uuid_value=NULL;
354
355
356 static void
357 dcerpcstat_start_button_clicked(GtkWidget *item _U_, gpointer data _U_)
358 {
359         GString *str;
360         const char *filter;
361
362         str = g_string_new("dcerpc,srt");
363         g_string_sprintfa(str,
364             ",%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x,%u.%u",
365             dcerpc_uuid_program->Data1, dcerpc_uuid_program->Data2,
366             dcerpc_uuid_program->Data3,
367             dcerpc_uuid_program->Data4[0], dcerpc_uuid_program->Data4[1],
368             dcerpc_uuid_program->Data4[2], dcerpc_uuid_program->Data4[3],
369             dcerpc_uuid_program->Data4[4], dcerpc_uuid_program->Data4[5],
370             dcerpc_uuid_program->Data4[6], dcerpc_uuid_program->Data4[7],
371             dcerpc_version, 0);
372         filter=gtk_entry_get_text(GTK_ENTRY(filter_entry));
373         if(filter[0]!=0){
374                 g_string_sprintfa(str, ",%s", filter);
375         }
376
377         gtk_dcerpcstat_init(str->str,NULL);
378         g_string_free(str, TRUE);
379 }
380
381
382 static void
383 dcerpcstat_version_select(GtkWidget *item _U_, gpointer key)
384 {
385         int vers=(long)key;
386
387         dcerpc_version=vers;
388 }
389
390
391
392
393 static void *
394 dcerpcstat_find_vers(gpointer *key, gpointer *value _U_, gpointer *user_data _U_)
395 {
396         dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
397         GtkWidget *menu_item;
398         char vs[5];
399
400         if(!uuid_equal((&k->uuid), dcerpc_uuid_program)){
401                 return NULL;
402         }
403
404         g_snprintf(vs, 5, "%u",k->ver);
405         menu_item=gtk_menu_item_new_with_label(vs);
406         SIGNAL_CONNECT(menu_item, "activate", dcerpcstat_version_select,
407                        ((long)k->ver));
408         gtk_widget_show(menu_item);
409         gtk_menu_append(GTK_MENU(vers_menu), menu_item);
410
411         if(dcerpc_version==0xffff){
412                 dcerpc_version=k->ver;
413         }
414
415         return NULL;
416 }
417
418
419 static void
420 dcerpcstat_program_select(GtkWidget *item _U_, gpointer key)
421 {
422         dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
423
424         dcerpc_uuid_program=&k->uuid;
425
426         /* change version menu */
427         dcerpc_version=0xffff;
428         gtk_object_destroy(GTK_OBJECT(vers_menu));
429         vers_menu=gtk_menu_new();
430         g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
431         gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
432 }
433
434
435 static GtkWidget *program_submenu_menu;
436 static GtkWidget *program_submenu_item;
437 static GtkWidget *program_submenu_label;
438 static int program_subitem_index;
439 static const char *first_menu_name;
440 static void 
441 dcerpcstat_add_program_to_menu(dcerpc_uuid_key *k, dcerpc_uuid_value *v)
442 {
443         GtkWidget *program_menu_item;
444         GtkWidget *box;
445         char str[64];
446
447         switch(program_subitem_index%15){
448         case 0:
449
450                 first_menu_name=v->name;
451                 g_snprintf(str,63,"%s ...",v->name);
452                 program_submenu_item=gtk_menu_item_new();
453                 box=gtk_hbox_new(TRUE,0);
454                 gtk_container_add(GTK_CONTAINER(program_submenu_item), box);
455                 
456                 program_submenu_label=gtk_label_new(str);
457                 gtk_box_pack_start(GTK_BOX(box), program_submenu_label, TRUE, TRUE, 0);
458                 gtk_widget_show(program_submenu_label);
459                 gtk_widget_show(box);
460
461                 gtk_menu_append(GTK_MENU(prog_menu), program_submenu_item);
462                 gtk_widget_show(program_submenu_item);
463
464                 program_submenu_menu=gtk_menu_new();
465                 gtk_menu_item_set_submenu(GTK_MENU_ITEM(program_submenu_item), program_submenu_menu);
466                 break;
467         case 14:
468                 g_snprintf(str,63,"%s - %s",first_menu_name,v->name);
469                 gtk_label_set_text(GTK_LABEL(program_submenu_label), str);
470                 break;
471 /*qqq*/
472         }
473         program_subitem_index++;                
474
475         program_menu_item=gtk_menu_item_new_with_label(v->name);
476         SIGNAL_CONNECT(program_menu_item, "activate", dcerpcstat_program_select, k);
477
478         gtk_widget_show(program_menu_item);
479         gtk_menu_append(GTK_MENU(program_submenu_menu), program_menu_item);
480
481         if(!dcerpc_uuid_program){
482                 dcerpc_uuid_program=&k->uuid;
483         }
484
485         return;
486 }
487
488 static void *
489 dcerpcstat_find_next_program(gpointer *key, gpointer *value, gpointer *user_data _U_)
490 {
491         dcerpc_uuid_key *k=(dcerpc_uuid_key *)key;
492         dcerpc_uuid_value *v=(dcerpc_uuid_value *)value;
493
494         /* first time called, just set new_uuid to this one */
495         if((current_uuid_key==NULL)&&(new_uuid_key==NULL)){
496                 new_uuid_key=k;
497                 new_uuid_value=v;
498                 return NULL;
499         }
500
501         /* if we havent got a current one yet, just check the new
502            and scan for the first one alphabetically  */
503         if(current_uuid_key==NULL){
504                 if(strcmp(new_uuid_value->name, v->name)>0){
505                         new_uuid_key=k;
506                         new_uuid_value=v;
507                         return NULL;
508                 }
509                 return NULL;
510         }
511
512         /* searching for the next one we are only interested in those
513            that sorts alphabetically after the current one */
514         if(strcmp(current_uuid_value->name, v->name)>=0){
515                 /* this one doesnt so just skip it */
516                 return NULL;
517         }
518
519         /* is it the first potential new entry? */
520         if(new_uuid_key==NULL){
521                 new_uuid_key=k;
522                 new_uuid_value=v;
523                 return NULL;
524         }
525
526         /* does it sort before the current new one? */
527         if(strcmp(new_uuid_value->name, v->name)>0){
528                 new_uuid_key=k;
529                 new_uuid_value=v;
530                 return NULL;
531         }
532
533         return NULL;
534 }
535
536
537 static void
538 dlg_destroy_cb(void)
539 {
540         dlg=NULL;
541 }
542
543
544 static void
545 gtk_dcerpcstat_cb(GtkWidget *w _U_, gpointer d _U_)
546 {
547         GtkWidget *dlg_box;
548         GtkWidget *prog_box, *prog_label, *prog_opt;
549         GtkWidget *vers_label;
550         GtkWidget *filter_box, *filter_bt;
551         GtkWidget *bbox, *start_button, *cancel_button;
552         const char *filter;
553         static construct_args_t args = {
554           "Service Response Time Statistics Filter",
555           FALSE,
556           FALSE,
557           FALSE
558         };
559
560         /* if the window is already open, bring it to front and
561            un-minimize it, as necessary */
562         if(dlg){
563                 reactivate_window(dlg);
564                 return;
565         }
566
567         dlg=dlg_window_new("Wireshark: Compute DCE-RPC SRT statistics");
568         gtk_window_set_default_size(GTK_WINDOW(dlg), 400, -1);
569
570         dlg_box=gtk_vbox_new(FALSE, 10);
571         gtk_container_border_width(GTK_CONTAINER(dlg_box), 10);
572         gtk_container_add(GTK_CONTAINER(dlg), dlg_box);
573         gtk_widget_show(dlg_box);
574
575         /* Program box */
576         prog_box=gtk_hbox_new(FALSE, 3);
577
578         /* Program label */
579         gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
580         prog_label=gtk_label_new("Program:");
581         gtk_box_pack_start(GTK_BOX(prog_box), prog_label, FALSE, FALSE, 0);
582         gtk_widget_show(prog_label);
583
584         /* Program menu */
585         prog_opt=gtk_option_menu_new();
586         prog_menu=gtk_menu_new();
587         current_uuid_key=NULL;
588         current_uuid_value=NULL;
589 /*qqq*/
590         program_submenu_item=NULL;
591         program_submenu_menu=NULL;
592         program_subitem_index=0;
593         do {
594                 new_uuid_key=NULL;
595                 new_uuid_value=NULL;
596                 g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_next_program, NULL);
597                 if(new_uuid_key){
598                         dcerpcstat_add_program_to_menu(new_uuid_key, new_uuid_value);
599                 }
600                 current_uuid_key=new_uuid_key;
601                 current_uuid_value=new_uuid_value;
602         } while(new_uuid_key!=NULL);
603
604         gtk_option_menu_set_menu(GTK_OPTION_MENU(prog_opt), prog_menu);
605         gtk_box_pack_start(GTK_BOX(prog_box), prog_opt, TRUE, TRUE, 0);
606         gtk_widget_show(prog_opt);
607
608         /* Version label */
609         gtk_container_set_border_width(GTK_CONTAINER(prog_box), 10);
610         vers_label=gtk_label_new("Version:");
611         gtk_box_pack_start(GTK_BOX(prog_box), vers_label, FALSE, FALSE, 0);
612         gtk_widget_show(vers_label);
613
614         /* Version menu */
615         vers_opt=gtk_option_menu_new();
616         vers_menu=gtk_menu_new();
617         dcerpc_version=0xffff;
618         g_hash_table_foreach(dcerpc_uuids, (GHFunc)dcerpcstat_find_vers, NULL);
619         gtk_option_menu_set_menu(GTK_OPTION_MENU(vers_opt), vers_menu);
620         gtk_box_pack_start(GTK_BOX(prog_box), vers_opt, TRUE, TRUE, 0);
621         gtk_widget_show(vers_opt);
622
623         gtk_box_pack_start(GTK_BOX(dlg_box), prog_box, TRUE, TRUE, 0);
624         gtk_widget_show(prog_box);
625
626         /* Filter box */
627         filter_box=gtk_hbox_new(FALSE, 3);
628
629         /* Filter label */
630         filter_bt=BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
631         SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
632         gtk_box_pack_start(GTK_BOX(filter_box), filter_bt, FALSE, FALSE, 0);
633         gtk_widget_show(filter_bt);
634
635         /* Filter entry */
636         filter_entry=gtk_entry_new();
637         SIGNAL_CONNECT(filter_entry, "changed", filter_te_syntax_check_cb, NULL);
638         gtk_box_pack_start(GTK_BOX(filter_box), filter_entry, TRUE, TRUE, 0);
639         filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
640         if(filter){
641                 gtk_entry_set_text(GTK_ENTRY(filter_entry), filter);
642         }
643         gtk_widget_show(filter_entry);
644         
645         gtk_box_pack_start(GTK_BOX(dlg_box), filter_box, TRUE, TRUE, 0);
646         gtk_widget_show(filter_box);
647
648         g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_entry);
649
650         /* button box */
651         bbox = dlg_button_row_new(WIRESHARK_STOCK_CREATE_STAT, GTK_STOCK_CANCEL, NULL);
652         gtk_box_pack_start(GTK_BOX(dlg_box), bbox, FALSE, FALSE, 0);
653         gtk_widget_show(bbox);
654
655         start_button = g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_CREATE_STAT);
656         g_signal_connect_swapped(start_button, "clicked", 
657                               G_CALLBACK(dcerpcstat_start_button_clicked), NULL);
658
659         cancel_button = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
660         window_set_cancel_button(dlg, cancel_button, window_cancel_button_cb);
661
662         SIGNAL_CONNECT(dlg, "delete_event", window_delete_event_cb, NULL);
663         SIGNAL_CONNECT(dlg, "destroy", dlg_destroy_cb, NULL);
664
665         /* Catch the "activate" signal on the filter text entry, so that
666            if the user types Return there, we act as if the "Create Stat"
667            button had been selected, as happens if Return is typed if some
668            widget that *doesn't* handle the Return key has the input
669            focus. */
670         dlg_set_activate(filter_entry, start_button);
671
672         gtk_widget_grab_default(start_button );
673
674         /* Give the initial focus to the "Filter" entry box. */
675         gtk_widget_grab_focus(filter_entry);
676
677         gtk_widget_show_all(dlg);
678         window_present(dlg);
679 }
680
681 void
682 register_tap_listener_gtkdcerpcstat(void)
683 {
684         register_stat_cmd_arg("dcerpc,srt,", gtk_dcerpcstat_init,NULL);
685
686         register_stat_menu_item("DCE-RPC...", REGISTER_STAT_GROUP_RESPONSE_TIME,
687             gtk_dcerpcstat_cb, NULL, NULL, NULL);
688 }