Add ws_load_library and ws_module_open, which respectively call
[obnox/wireshark/wip.git] / gtk / main.c
index 7bfd2ff18d41a8293b9ec05a80ff8c06a9d4a1ed..bb3bbdce6cdb1fa97184c440a056476ea3de9eff 100644 (file)
 #include "../capture-wpcap.h"
 #include "../capture_wpcap_packet.h"
 #include <tchar.h> /* Needed for Unicode */
+#include <wsutil/unicode-utils.h>
 #include <commctrl.h>
+#include <shellapi.h>
 #endif /* _WIN32 */
 
 /* GTK related */
@@ -220,6 +222,7 @@ guint  tap_update_timer_id;
 static gboolean has_console;   /* TRUE if app has console */
 static void destroy_console(void);
 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
+static gboolean dll_set = FALSE; /* Did we sucessfully trim our DLL path? */
 #endif
 static void console_log_handler(const char *log_domain,
     GLogLevelFlags log_level, const char *message, gpointer user_data);
@@ -524,12 +527,14 @@ GList *
 get_ip_address_list_from_packet_list_row(gpointer data)
 {
     gint    row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
+#ifdef NEW_PACKET_LIST
+    gint    column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
+#else
     gint    column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
+#endif
     gint    col;
     frame_data *fdata;
     GList      *addr_list = NULL;
-    int         err;
-    gchar       *err_info;
 
 #ifdef NEW_PACKET_LIST
     fdata = (frame_data *) new_packet_list_get_row_data(row);
@@ -540,12 +545,8 @@ get_ip_address_list_from_packet_list_row(gpointer data)
     if (fdata != NULL) {
         epan_dissect_t edt;
 
-        if (!cf_read_frame (&cfile, fdata, &err, &err_info))
-       {
-            simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                      cf_read_error_message(err, err_info), cfile.filename);
-            return NULL;
-        }
+        if (!cf_read_frame (&cfile, fdata))
+            return NULL; /* error reading the frame */
 
         epan_dissect_init(&edt, FALSE, FALSE);
         col_custom_prime_edt(&edt, &cfile.cinfo);
@@ -575,11 +576,13 @@ static gchar *
 get_filter_from_packet_list_row_and_column(gpointer data)
 {
     gint    row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
+#ifdef NEW_PACKET_LIST
+    gint    column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
+#else
     gint    column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
+#endif
     frame_data *fdata;
     gchar      *buf=NULL;
-    int         err;
-    gchar       *err_info;
 
 #ifdef NEW_PACKET_LIST
     fdata = (frame_data *) new_packet_list_get_row_data(row);
@@ -590,11 +593,8 @@ get_filter_from_packet_list_row_and_column(gpointer data)
     if (fdata != NULL) {
         epan_dissect_t edt;
 
-        if (!cf_read_frame(&cfile, fdata, &err, &err_info)) {
-            simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-                      cf_read_error_message(err, err_info), cfile.filename);
-            return NULL;
-        }
+        if (!cf_read_frame(&cfile, fdata))
+            return NULL; /* error reading the frame */
         /* proto tree, visible. We need a proto tree if there's custom columns */
         epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
         col_custom_prime_edt(&edt, &cfile.cinfo);
@@ -691,19 +691,25 @@ copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E acti
 
 
 /* mark as reference time frame */
-static void
+void
 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
   if (row == -1)
     return;
   if (set) {
     frame->flags.ref_time=1;
+       cfile.ref_time_count++;
   } else {
     frame->flags.ref_time=0;
+    cfile.ref_time_count--;
   }
   cf_reftime_packets(&cfile);
 #ifdef NEW_PACKET_LIST
-  if (!frame->flags.ref_time && !frame->flags.passed_dfilter)
+  if (!frame->flags.ref_time && !frame->flags.passed_dfilter) {
+    new_packet_list_freeze();
+    cfile.displayed_count--;
     new_packet_list_recreate_visible_rows();
+    new_packet_list_thaw();
+  }
   new_packet_list_queue_draw();
 #endif
 }
@@ -757,10 +763,10 @@ reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
     }
     break;
   case REFTIME_FIND_NEXT:
-    find_previous_next_frame_with_filter("frame.ref_time", FALSE);
+    cf_find_packet_time_reference(&cfile, SD_FORWARD);
     break;
   case REFTIME_FIND_PREV:
-    find_previous_next_frame_with_filter("frame.ref_time", TRUE);
+    cf_find_packet_time_reference(&cfile, SD_BACKWARD);
     break;
   }
 }
@@ -768,13 +774,13 @@ reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
 void
 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
 {
-    find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
+    cf_find_packet_marked(&cfile, SD_FORWARD);
 }
 
 void
 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
 {
-    find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
+    cf_find_packet_marked(&cfile, SD_BACKWARD);
 }
 
 static void
@@ -1403,21 +1409,19 @@ resolv_update_cb(gpointer data _U_)
 }
 
 
-/* Set the file name in the name for the main window and in the name for the main window's icon. */
-static void
+/* Set main_window_name and it's icon title to the capture filename */
+void
 set_display_filename(capture_file *cf)
 {
-  gchar       *win_name;
+  gchar *window_name;
 
-  if (!cf->is_tempfile && cf->filename) {
-    /* Add this filename to the list of recent files in the "Recent Files" submenu */
-    add_menu_recent_capture_file(cf->filename);
+  if (cf->filename) {
+    window_name = g_strdup_printf("%s", cf_get_display_name(cf));
+    set_main_window_name(window_name);
+    g_free(window_name);
+  } else {
+    set_main_window_name("The Wireshark Network Analyzer");
   }
-
-  /* window title */
-  win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
-  set_main_window_name(win_name);
-  g_free(win_name);
 }
 
 GtkWidget           *close_dlg = NULL;
@@ -1496,6 +1500,17 @@ main_cf_cb_file_read_started(capture_file *cf _U_)
 static void
 main_cf_cb_file_read_finished(capture_file *cf)
 {
+    gchar *dir_path;
+
+    if (!cf->is_tempfile && cf->filename) {
+        /* Add this filename to the list of recent files in the "Recent Files" submenu */
+        add_menu_recent_capture_file(cf->filename);
+
+        /* Remember folder for next Open dialog and save it in recent */
+       dir_path = get_dirname(g_strdup(cf->filename));
+        set_last_open_dir(dir_path);
+        g_free(dir_path);
+    }
     set_display_filename(cf);
 
     /* Enable menu items that make sense if you have a capture file you've
@@ -1556,8 +1571,6 @@ main_capture_set_main_window_title(capture_options *capture_opts)
     if(capture_opts->iface) {
         g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
     }
-    g_string_append(title, "- Wireshark");
-
     set_main_window_name(title->str);
     g_string_free(title, TRUE);
 }
@@ -1607,6 +1620,10 @@ main_capture_cb_capture_update_finished(capture_options *capture_opts)
     capture_file *cf = capture_opts->cf;
     static GList *icon_list = NULL;
 
+    if (!cf->is_tempfile && cf->filename) {
+        /* Add this filename to the list of recent files in the "Recent Files" submenu */
+        add_menu_recent_capture_file(cf->filename);
+    }
     set_display_filename(cf);
 
     /* Enable menu items that make sense if you're not currently running
@@ -1827,7 +1844,7 @@ main_capture_callback(gint event, capture_options *capture_opts, gpointer user_d
 static void
 get_gui_compiled_info(GString *str)
 {
-  get_epan_compiled_version_info(str);
+  epan_get_compiled_version_info(str);
 
   g_string_append(str, ", ");
 #ifdef HAVE_LIBPORTAUDIO
@@ -1855,6 +1872,8 @@ get_gui_compiled_info(GString *str)
 static void
 get_gui_runtime_info(GString *str)
 {
+  epan_get_runtime_version_info(str);
+
 #ifdef HAVE_AIRPCAP
   g_string_append(str, ", ");
   get_runtime_airpcap_version(str);
@@ -1864,7 +1883,6 @@ get_gui_runtime_info(GString *str)
     g_string_append(str, ", ");
     u3_runtime_info(str);
   }
-
 }
 
 static e_prefs *
@@ -2025,6 +2043,8 @@ main(int argc, char *argv[])
 
 #ifdef _WIN32
   WSADATA             wsaData;
+  LPWSTR              *wc_argv;
+  int                  wc_argc, i;
 #endif  /* _WIN32 */
 
   char                *rf_path;
@@ -2053,7 +2073,7 @@ main(int argc, char *argv[])
   GtkWidget           *splash_win = NULL;
   GLogLevelFlags       log_flags;
   guint                go_to_packet = 0;
-  gboolean             jump_backwards = FALSE, saved_bw = FALSE;
+  gboolean             jump_backwards = FALSE;
   dfilter_t           *jump_to_filter = NULL;
   int                  optind_initial;
   int                  status;
@@ -2081,6 +2101,21 @@ main(int argc, char *argv[])
 
   static const char optstring[] = OPTSTRING;
 
+#ifdef _WIN32
+  /* Convert our arg list to UTF-8. */
+  wc_argv = CommandLineToArgvW(GetCommandLineW(), &wc_argc);
+  if (wc_argv && wc_argc == argc) {
+    for (i = 0; i < argc; i++) {
+      argv[i] = g_strdup(utf_16to8(wc_argv[i]));
+    }
+  } /* XXX else bail because something is horribly, horribly wrong? */
+
+  if (!dll_set) {
+    simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "SetDllDirectory failed (%d)!\n", GetLastError());
+    /* XXX - Exit? */
+  }
+#endif /* _WIN32 */
+
   /*
    * Get credential information for later use, and drop privileges
    * before doing anything else.
@@ -2243,7 +2278,7 @@ main(int argc, char *argv[])
 
   /* Init the "Open file" dialog directory */
   /* (do this after the path settings are processed) */
-  
+
   /* Read the profile dependent (static part) of the recent file. */
   /* Only the static part of it will be read, as we don't have the gui now to fill the */
   /* recent lists which is done in the dynamic part. */
@@ -2255,7 +2290,7 @@ main(int argc, char *argv[])
                  rf_path, strerror(rf_open_errno));
   }
 
-  if (recent.gui_fileopen_remembered_dir && 
+  if (recent.gui_fileopen_remembered_dir &&
       test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
     set_last_open_dir(recent.gui_fileopen_remembered_dir);
   } else {
@@ -2587,12 +2622,7 @@ main(int argc, char *argv[])
        /* We may set "last_open_dir" to "cf_name", and if we change
           "last_open_dir" later, we free the old value, so we have to
           set "cf_name" to something that's been allocated. */
-#if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
-        /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
-        cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
-#else
         cf_name = g_strdup(optarg);
-#endif
         break;
       case 'R':        /* Read file filter */
         rfilter = optarg;
@@ -2671,19 +2701,12 @@ main(int argc, char *argv[])
        * file - yes, you could have "-r" as the last part of the command,
        * but that's a bit ugly.
        */
-#if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
-      /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
-      cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
-#else
       cf_name = g_strdup(argv[0]);
-#endif
     }
     argc--;
     argv++;
   }
 
-
-
   if (argc != 0) {
     /*
      * Extra command line arguments were specified; complain.
@@ -2926,15 +2949,11 @@ main(int argc, char *argv[])
             /* try to compile given filter */
             if (!dfilter_compile(jfilter, &jump_to_filter)) {
               bad_dfilter_alert_box(jfilter);
-            } else
-            {
+            } else {
               /* Filter ok, jump to the first packet matching the filter
                  conditions. Default search direction is forward, but if
                  option d was given, search backwards */
-              saved_bw = cfile.sbackward;
-              cfile.sbackward = jump_backwards;
-              cf_find_packet_dfilter(&cfile, jump_to_filter);
-              cfile.sbackward = saved_bw;
+              cf_find_packet_dfilter(&cfile, jump_to_filter, jump_backwards);
             }
           }
           break;
@@ -2944,6 +2963,17 @@ main(int argc, char *argv[])
           exit(0);
           break;
         }
+
+       /* If the filename is not the absolute path, prepend the current dir. This happens
+          when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
+       if (!g_path_is_absolute(cf_name)) {
+         char *old_cf_name = cf_name;
+         char *pwd = g_get_current_dir();
+         cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name);
+         g_free(old_cf_name);
+         g_free(pwd);
+       }
+
         /* Save the name of the containing directory specified in the
            path name, if any; we can write over cf_name, which is a
            good thing, given that "get_dirname()" does write over its
@@ -3068,6 +3098,12 @@ WinMain (struct HINSTANCE__ *hInstance,
         int                 nCmdShow)
 {
   INITCOMMONCONTROLSEX comm_ctrl;
+  typedef BOOL (*SetDllDirectoryHandler)(LPCTSTR);
+  SetDllDirectoryHandler PSetDllDirectory;
+
+  if (PSetDllDirectory = (SetDllDirectoryHandler) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "SetDllDirectoryW")) {
+    dll_set = PSetDllDirectory(_T(""));
+  }
 
   /* Initialize our controls. Required for native Windows file dialogs. */
   memset (&comm_ctrl, 0, sizeof(comm_ctrl));
@@ -3080,7 +3116,7 @@ WinMain (struct HINSTANCE__ *hInstance,
   InitCommonControlsEx(&comm_ctrl);
 
   /* RichEd20.DLL is needed for filter entries. */
-  LoadLibrary(_T("riched20.dll"));
+  ws_load_library("riched20.dll");
 
   has_console = FALSE;
   return main (__argc, __argv);
@@ -3491,7 +3527,7 @@ main_widgets_show_or_hide(void)
 
 
 /* called, when the window state changes (minimized, maximized, ...) */
-static int
+static gboolean
 window_state_event_cb (GtkWidget *widget _U_,
                        GdkEvent *event,
                        gpointer  data _U_)
@@ -3511,7 +3547,7 @@ window_state_event_cb (GtkWidget *widget _U_,
 
 
 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
-static int
+static gboolean
 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
 {
     if (event->keyval == GDK_F8) {
@@ -3551,14 +3587,10 @@ static void
 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
 {
     GtkAccelGroup *accel;
-    gchar         *title;
-
-    /* use user-defined title if preference is set */
-    title = create_user_window_title("The Wireshark Network Analyzer");
 
     /* Main window */
-    top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
-    g_free(title);
+    top_level = window_new(GTK_WINDOW_TOPLEVEL, "");
+    set_main_window_name("The Wireshark Network Analyzer");
 
     gtk_widget_set_name(top_level, "main window");
     g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
@@ -3726,7 +3758,7 @@ void change_configuration_profile (const gchar *profile_name)
                  "Could not open common recent file\n\"%s\": %s.",
                  rf_path, strerror(rf_open_errno));
    }
-   if (recent.gui_fileopen_remembered_dir && 
+   if (recent.gui_fileopen_remembered_dir &&
        test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
      set_last_open_dir(recent.gui_fileopen_remembered_dir);
    }
@@ -3738,7 +3770,7 @@ void change_configuration_profile (const gchar *profile_name)
    prefs_apply_all();
 
    /* Update window view and redraw the toolbar */
-   update_main_window_name();
+   update_main_window_title();
    toolbar_redraw_all();
 
    /* Enable all protocols and disable from the disabled list */