Move merge.{h,c} into wiretap: these modules use wiretap to merge files.
[metze/wireshark/wip.git] / ui / win32 / file_dlg_win32.c
index 1c3ed0239a89dc5840aaf99f374b771a79f12062..955767f1565db4173c91291379c56ee30e5bc5bb 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
 
 #include <stdio.h>
 #include <tchar.h>
 #include <windowsx.h>
 #include <commdlg.h>
 #include <richedit.h>
+#include <strsafe.h>
 
 #include <gtk/gtk.h>
 
+#include "wsutil/file_util.h"
+#include "wsutil/unicode-utils.h"
+
+#include "wiretap/merge.h"
+
 #include "epan/filesystem.h"
 #include "epan/addr_resolv.h"
 #include "epan/prefs.h"
-#include "epan/dissectors/packet-ssl.h"
-#include "epan/dissectors/packet-ssl-utils.h"
-#include "wsutil/file_util.h"
-#include "wsutil/unicode-utils.h"
+#include "epan/print.h"
 
-#include "../alert_box.h"
-#include "../color.h"
-#include "../print.h"
-#include "../simple_dialog.h"
-#include "../util.h"
-#include "../color_filters.h"
-#include "../merge.h"
+#include "color.h"
+#include "color_filters.h"
 
+#include "ui/alert_box.h"
+#include "ui/help_url.h"
+#include "ui/file_dialog.h"
 #include "ui/last_open_dir.h"
+#include "ui/simple_dialog.h"
+#include "ui/ssl_key_export.h"
+#include "ui/util.h"
 
+#include "ui/gtk/main.h"
 #include "ui/gtk/file_dlg.h"
 #include "ui/gtk/capture_file_dlg.h"
-#include "ui/gtk/main.h"
 #include "ui/gtk/menus.h"
 #include "ui/gtk/drag_and_drop.h"
 #include "ui/gtk/capture_dlg.h"
 #include "file_dlg_win32.h"
-#include "ui/gtk/help_dlg.h"
 #include "ui/gtk/export_sslkeys.h"
 
-typedef enum {
-    merge_append,
-    merge_chrono,
-    merge_prepend
-} merge_action_e;
-
 #define FILE_OPEN_DEFAULT 1 /* All Files */
 
 #define FILE_MERGE_DEFAULT FILE_OPEN_DEFAULT
 
-#define FILE_SAVE_DEFAULT 1 /* Wireshark/tcpdump */
-
 #define FILE_TYPES_EXPORT \
     _T("Plain text (*.txt)\0")                           _T("*.txt\0")   \
     _T("PostScript (*.ps)\0")                            _T("*.ps\0")    \
@@ -107,37 +100,25 @@ typedef enum {
 
 #define FILE_DEFAULT_COLOR 2
 
-/*
- * We should probably test the SDK version instead of the compiler version,
- * but this should work for our purposes.
- */
-#if (_MSC_VER <= 1200)
-static UINT CALLBACK open_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
-static UINT CALLBACK save_as_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
-static UINT CALLBACK merge_file_hook_proc(HWND mf_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
-static UINT CALLBACK export_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
-static UINT CALLBACK export_raw_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
-static UINT CALLBACK export_sslkeys_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
-#else
 static UINT_PTR CALLBACK open_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
 static UINT_PTR CALLBACK save_as_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
+static UINT_PTR CALLBACK export_specified_packets_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
 static UINT_PTR CALLBACK merge_file_hook_proc(HWND mf_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
 static UINT_PTR CALLBACK export_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
 static UINT_PTR CALLBACK export_raw_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
 static UINT_PTR CALLBACK export_sslkeys_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
-#endif /* (_MSC_VER <= 1200) */
-
 static void range_update_dynamics(HWND sf_hwnd, packet_range_t *range);
 static void range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range);
 static void range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t *range);
 
-static TCHAR *build_file_type_list(gboolean save, int *item_to_select);
-static int file_type_from_list_index(gboolean save, int index);
+static TCHAR *build_file_open_type_list(void);
+static TCHAR *build_file_save_type_list(GArray *savable_file_types);
 
-static int            filetype;
-static packet_range_t g_range;
-static merge_action_e merge_action;
-static print_args_t   print_args;
+static int             g_filetype;
+static gboolean        g_compressed;
+static packet_range_t *g_range;
+static merge_action_e  g_merge_action;
+static print_args_t    print_args;
 /* XXX - The reason g_sf_hwnd exists is so that we can call
  *       range_update_dynamics() from anywhere; it's currently
  *       static, but if we move to using the native Windows
@@ -149,8 +130,8 @@ static print_args_t   print_args;
  *       should arguably be modal to the window for the file
  *       being opened/saved/etc.).
  */
-static HWND           g_sf_hwnd = NULL;
-static char *dfilter_str = NULL;
+static HWND  g_sf_hwnd = NULL;
+static char *g_dfilter_str = NULL;
 
 /*
  * According to http://msdn.microsoft.com/en-us/library/bb776913.aspx
@@ -159,17 +140,29 @@ static char *dfilter_str = NULL;
  */
 
 gboolean
-win32_open_file (HWND h_wnd) {
+win32_open_file (HWND h_wnd, GString *file_name, GString *display_filter) {
     OPENFILENAME *ofn;
-    TCHAR  file_name[MAX_PATH] = _T("");
-    int    err;
-    char  *dirname;
-    dfilter_t *dfp;
-    int    ofnsize;
+    TCHAR file_name16[MAX_PATH] = _T("");
+    int ofnsize;
+    gboolean gofn_ok;
 #if (_MSC_VER >= 1500)
     OSVERSIONINFO osvi;
 #endif
 
+    if (!file_name || !display_filter)
+        return FALSE;
+
+    if (file_name->len > 0) {
+        StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
+    }
+
+    if (display_filter->len > 0) {
+        g_dfilter_str = g_strdup(display_filter->str);
+    } else if (g_dfilter_str) {
+        g_free(g_dfilter_str);
+        g_dfilter_str = NULL;
+    }
+
     /* Remarks on OPENFILENAME_SIZE_VERSION_400:
      *
      * MSDN states that OPENFILENAME_SIZE_VERSION_400 should be used with
@@ -207,16 +200,12 @@ win32_open_file (HWND h_wnd) {
 
     ofn->lStructSize = ofnsize;
     ofn->hwndOwner = h_wnd;
-#if (_MSC_VER <= 1200)
-    ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
-#else
     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
-#endif
-    ofn->lpstrFilter = build_file_type_list(FALSE /*!save*/, NULL);
+    ofn->lpstrFilter = build_file_open_type_list();
     ofn->lpstrCustomFilter = NULL;
     ofn->nMaxCustFilter = 0;
     ofn->nFilterIndex = FILE_OPEN_DEFAULT;
-    ofn->lpstrFile = file_name;
+    ofn->lpstrFile = file_name16;
     ofn->nMaxFile = MAX_PATH;
     ofn->lpstrFileTitle = NULL;
     ofn->nMaxFileTitle = 0;
@@ -233,47 +222,144 @@ win32_open_file (HWND h_wnd) {
     ofn->lpfnHook = open_file_hook_proc;
     ofn->lpTemplateName = _T("WIRESHARK_OPENFILENAME_TEMPLATE");
 
-    if (GetOpenFileName(ofn)) {
-        g_free( (void *) ofn->lpstrFilter);
-        g_free( (void *) ofn);
+    gofn_ok = GetOpenFileName(ofn);
 
-        if (cf_open(&cfile, utf_16to8(file_name), FALSE, &err) != CF_OK) {
-            return FALSE;
-        }
+    if (gofn_ok) {
+        g_string_printf(file_name, "%s", utf_16to8(file_name16));
+        g_string_printf(display_filter, "%s", g_dfilter_str ? g_dfilter_str : "");
+    }
 
-        /* apply our filter */
-        if (dfilter_compile(dfilter_str, &dfp)) {
-            cf_set_rfcode(&cfile, dfp);
-        }
+    g_free( (void *) ofn->lpstrFilter);
+    g_free( (void *) ofn);
+    g_free(g_dfilter_str);
+    g_dfilter_str = NULL;
+    return gofn_ok;
+}
 
-        switch (cf_read(&cfile, FALSE)) {
-            case CF_READ_OK:
-            case CF_READ_ERROR:
-                dirname = get_dirname(utf_16to8(file_name));
-                set_last_open_dir(dirname);
-                return TRUE;
-                break;
-        }
+check_savability_t
+win32_check_save_as_with_comments(HWND parent, capture_file *cf, int file_type)
+{
+    guint32        comment_types;
+    gint           response;
+
+    /* What types of comments do we have? */
+    comment_types = cf_comment_types(cf);
+
+    /* Does the file's format support all the comments we have? */
+    if (wtap_dump_supports_comment_types(cf->cd_t, comment_types)) {
+        /* Yes.  Let the save happen; we can save all the comments, so
+           there's no need to delete them. */
+        return SAVE;
+    }
+
+    /* No. Are there formats in which we can write this file that
+       supports all the comments in this file? */
+    if (wtap_dump_can_write(cf->linktypes, comment_types)) {
+        /* Yes.  Offer the user a choice of "Save in a format that
+           supports comments", "Discard comments and save in the
+           format you selected", or "Cancel", meaning "don't bother
+           saving the file at all".
+
+           XXX - sadly, customizing buttons in a MessageBox() is
+           Really Painful; there are tricks out there to do it
+           with a "computer-based training" hook that gets called
+           before the window is activated and sets the text of the
+           buttons, but if you change the text of the buttons you
+           also have to make the buttons bigger.  There *has* to
+           be a better way of doing that, given that Microsoft's
+           own UI guidelines have examples of dialog boxes with
+           action buttons that have custom labels, but maybe we'd
+           have to go with Windows Forms or XAML or whatever the
+           heck the technology of the week is.
+
+           Therefore, we ask a yes-or-no question - "do you want
+           to discard the comments and save in the format you
+           chose?" - and have "no" mean "I want to save the
+           file but I don't want to discard the comments, meaning
+           we should reopen the dialog and not offer the user any
+           choices that would involve discarding the comments. */
+        response = MessageBox(parent,
+  _T("The capture has comments, but the file format you chose ")
+  _T("doesn't support comments.  Do you want to discard the comments ")
+  _T("and save in the format you chose?"),
+                              _T("Wireshark: Save File As"),
+                              MB_YESNOCANCEL|MB_ICONWARNING|MB_DEFBUTTON2);
     } else {
-        g_free( (void *) ofn->lpstrFilter);
-        g_free( (void *) ofn);
+        /* No.  Offer the user a choice of "Discard comments and
+           save in the format you selected" or "Cancel".
+
+           XXX - see rant above. */
+        response = MessageBox(parent,
+  _T("The capture has comments, but no file format in which it ")
+  _T("can be saved supports comments.  Do you want to discard ")
+  _T("the comments and save in the format you chose?"),
+                              _T("Wireshark: Save File As"),
+                              MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2);
     }
-    return FALSE;
-}
 
+    switch (response) {
+
+    case IDNO: /* "No" means "Save in another format" in the first dialog */
+        /* OK, the only other format we support is pcap-ng.  Make that
+           the one and only format in the combo box, and return to
+           let the user continue with the dialog.
+
+           XXX - removing all the formats from the combo box will clear
+           the compressed checkbox; get the current value and restore
+           it.
+
+           XXX - we know pcap-ng can be compressed; if we ever end up
+           supporting saving comments in a format that *can't* be
+           compressed, such as NetMon format, we must check this. */
+        /* XXX - need a compressed checkbox here! */
+        return SAVE_IN_ANOTHER_FORMAT;
+
+    case IDYES: /* "Yes" means "Discard comments and save" in the first dialog */
+    case IDOK:  /* "OK" means "Discard comments and save" in the second dialog */
+        /* Save without the comments and, if that succeeds, delete the
+           comments. */
+        return SAVE_WITHOUT_COMMENTS;
+
+    case IDCANCEL:
+    default:
+        /* Just give up. */
+        return CANCELLED;
+    }
+}
 
-void
-win32_save_as_file(HWND h_wnd, action_after_save_e action_after_save, gpointer action_after_save_data) {
+gboolean
+win32_save_as_file(HWND h_wnd, capture_file *cf, GString *file_name, int *file_type,
+                   gboolean *compressed, gboolean must_support_all_comments)
+{
+    guint32 required_comment_types;
+    GArray *savable_file_types;
     OPENFILENAME *ofn;
     TCHAR  file_name16[MAX_PATH] = _T("");
-    GString *file_name8;
-    gchar *file_last_dot;
-    gchar *dirname;
-    int save_index;
     int    ofnsize;
+    gboolean gsfn_ok;
 #if (_MSC_VER >= 1500)
     OSVERSIONINFO osvi;
 #endif
+    gboolean discard_comments = FALSE;
+
+    if (!file_name || !file_type || !compressed)
+        return FALSE;
+
+    if (file_name->len > 0) {
+        StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
+    }
+
+    /* What types of comments do we have to support? */
+    if (must_support_all_comments)
+        required_comment_types = cf_comment_types(cf); /* all the ones the file has */
+    else
+        required_comment_types = 0; /* none of them */
+
+    savable_file_types = wtap_get_savable_file_types(cf->cd_t, cf->linktypes,
+                                                     required_comment_types);
+    if (savable_file_types == NULL)
+        return FALSE;  /* shouldn't happen - the "Save As..." item should be disabled if we can't save the file */
+    g_compressed = FALSE;
 
     /* see OPENFILENAME comment in win32_open_file */
 #if (_MSC_VER >= 1500)
@@ -292,15 +378,11 @@ win32_save_as_file(HWND h_wnd, action_after_save_e action_after_save, gpointer a
 
     ofn->lStructSize = ofnsize;
     ofn->hwndOwner = h_wnd;
-#if (_MSC_VER <= 1200)
-    ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
-#else
     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
-#endif
-    ofn->lpstrFilter = build_file_type_list(TRUE /*save*/, &save_index);
+    ofn->lpstrFilter = build_file_save_type_list(savable_file_types);
     ofn->lpstrCustomFilter = NULL;
     ofn->nMaxCustFilter = 0;
-    ofn->nFilterIndex = save_index;
+    ofn->nFilterIndex = 1;  /* the first entry is the best match; 1-origin indexing */
     ofn->lpstrFile = file_name16;
     ofn->nMaxFile = MAX_PATH;
     ofn->lpstrFileTitle = NULL;
@@ -312,115 +394,150 @@ win32_save_as_file(HWND h_wnd, action_after_save_e action_after_save, gpointer a
                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
     ofn->lpstrDefExt = NULL;
     ofn->lpfnHook = save_as_file_hook_proc;
-    ofn->lpTemplateName = _T("WIRESHARK_SAVEFILENAME_TEMPLATE");
+    ofn->lpTemplateName = _T("WIRESHARK_SAVEASFILENAME_TEMPLATE");
 
-    if (GetSaveFileName(ofn)) {
-        filetype = file_type_from_list_index(TRUE /*save*/, ofn->nFilterIndex);
-
-        /* append the default file extension if there's none given by the user */
-        /* (we expect a file extension to be at most 5 chars + the dot) */
-        file_name8 = g_string_new(utf_16to8(file_name16));
-        file_last_dot = strrchr(file_name8->str,'.');
-        if(file_last_dot == NULL || strlen(file_name8->str)-(file_last_dot-file_name8->str) > 5+1) {
-            if(wtap_file_extension_default_string(filetype) != NULL) {
-                g_string_append_printf(file_name8, ".%s", wtap_file_extension_default_string(filetype));
-            }
-        }
+    gsfn_ok = GetSaveFileName(ofn);
 
-        g_sf_hwnd = NULL;
-        /* Write out the packets (all, or only the ones from the current
-           range) to the file with the specified name. */
-
-        /* GetSaveFileName() already asked the user if he wants to overwrite the old file,        */
-        /* so if we are here, user already confirmed to overwrite - just delete the old file now. */
-        /* Note: Windows ws_unlink cannot delete a currently open file; Therefore the             */
-        /*       GetSaveFileName dialog has been coded to prevent doing a 'save as' to the        */
-        /*       currently open capture file.                                                     */
-        /* XX: Windows Wireshark is built with GLIB >= 2.6 these       */
-        /*     days so ws_unlink will properly convert the             */
-        /*     UTF8 filename to UTF16 & then do a _wunlink.            */
-        /* XX: if the cf_save fails, it will do a GTK simple_dialog()  */
-        /*     which is not useful while doing a Windows dialog.       */
-        /*     (A GTK dialog box will be generated and basically will  */
-        /*     only appear when the redisplayed Windows 'save_as-file' */
-        /*     dialog is dismissed. It will then need to be dismissed. */
-        /*     This should be fixed even though the cf_save()          */
-        /*     presumably should rarely fail in this case.             */
-        if ((ws_unlink(file_name8->str) != 0) && (errno == EACCES)) {
-            /* XXX: Is MessageBox the best way to pop up an error ? How to make text bold ? */
-            gchar *str = g_strdup_printf("Unable to delete file: %s\nPlease choose another name !", file_name8->str);
-            MessageBox( NULL, utf_8to16(str), _T("Error"), MB_ICONERROR | MB_APPLMODAL | MB_OK);
-            g_free(str);
-            goto AGAIN;
-        }
-        if (cf_save(&cfile, file_name8->str, &g_range, filetype, FALSE) != CF_OK) {
-            /* The write failed.  Try again. */
-        AGAIN:
-            g_string_free(file_name8, TRUE /* free_segment */);
-            g_free( (void *) ofn->lpstrFilter);
-            g_free( (void *) ofn);
-            win32_save_as_file(h_wnd, action_after_save, action_after_save_data);
-            return;
+    if (gsfn_ok) {
+        g_string_printf(file_name, "%s", utf_16to8(file_name16));
+        /* What file format was specified? */
+        *file_type = g_array_index(savable_file_types, int, ofn->nFilterIndex - 1);
+        *compressed = g_compressed;
+    } else {
+        /* User cancelled or closed the dialog, or an error occurred. */
+        if (CommDlgExtendedError() != 0) {
+            /* XXX - pop up some error here. FNERR_INVALIDFILENAME
+             * might be a user error; if so, they should know about
+             * it. For now we force a do-over.
+             */
+            g_string_truncate(file_name, 0);
+            gsfn_ok = TRUE;
         }
+    }
 
-        /* Save the directory name for future file dialogs. */
-        dirname = get_dirname(file_name8->str);  /* Overwrites cf_name */
-        set_last_open_dir(dirname);
+    g_sf_hwnd = NULL;
+    g_array_free(savable_file_types, TRUE);
+    g_free( (void *) ofn->lpstrFilter);
+    g_free( (void *) ofn);
+    return gsfn_ok;
+}
+
+gboolean
+win32_export_specified_packets_file(HWND h_wnd, GString *file_name,
+                                    int *file_type,
+                                    gboolean *compressed,
+                                    packet_range_t *range) {
+    GArray *savable_file_types;
+    OPENFILENAME *ofn;
+    TCHAR  file_name16[MAX_PATH] = _T("");
+    int    ofnsize;
+    gboolean gsfn_ok;
+#if (_MSC_VER >= 1500)
+    OSVERSIONINFO osvi;
+#endif
 
-        g_string_free(file_name8, TRUE /* free_segment */);
+    if (!file_name || !file_type || !compressed || !range)
+        return FALSE;
 
-        /* we have finished saving, do we have pending things to do? */
-        switch(action_after_save) {
-            case(after_save_no_action):
-                break;
-            case(after_save_open_dialog):
-                win32_open_file(h_wnd);
-                break;
-            case(after_save_open_recent_file):
-                menu_open_recent_file_cmd(action_after_save_data);
-                break;
-            case(after_save_open_dnd_file):
-                dnd_open_file_cmd(action_after_save_data);
-                break;
-            case(after_save_merge_dialog):
-                win32_merge_file(h_wnd);
-                break;
-#ifdef HAVE_LIBPCAP
-            case(after_save_capture_dialog):
-                capture_start_confirmed();
-                break;
+    if (file_name->len > 0) {
+        StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
+    }
+
+    savable_file_types = wtap_get_savable_file_types(cfile.cd_t,
+                                                     cfile.linktypes, 0);
+    if (savable_file_types == NULL)
+        return FALSE;  /* shouldn't happen - the "Save As..." item should be disabled if we can't save the file */
+
+    g_range = range;
+    g_compressed = FALSE;
+
+    /* see OPENFILENAME comment in win32_open_file */
+#if (_MSC_VER >= 1500)
+    SecureZeroMemory(&osvi, sizeof(OSVERSIONINFO));
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    GetVersionEx(&osvi);
+    if (osvi.dwMajorVersion >= 5) {
+        ofnsize = sizeof(OPENFILENAME);
+    } else {
+        ofnsize = OPENFILENAME_SIZE_VERSION_400;
+    }
+#else
+    ofnsize = sizeof(OPENFILENAME) + 12;
 #endif
-            case(after_save_close_file):
-                cf_close(&cfile);
-                break;
-            case(after_save_exit):
-                main_do_quit();
-                break;
-            default:
-                g_assert_not_reached();
+    ofn = g_malloc0(ofnsize);
+
+    ofn->lStructSize = ofnsize;
+    ofn->hwndOwner = h_wnd;
+    ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
+    ofn->lpstrFilter = build_file_save_type_list(savable_file_types);
+    ofn->lpstrCustomFilter = NULL;
+    ofn->nMaxCustFilter = 0;
+    ofn->nFilterIndex = 1;  /* the first entry is the best match; 1-origin indexing */
+    ofn->lpstrFile = file_name16;
+    ofn->nMaxFile = MAX_PATH;
+    ofn->lpstrFileTitle = NULL;
+    ofn->nMaxFileTitle = 0;
+    ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
+    ofn->lpstrTitle = _T("Wireshark: Export Specified Packets");
+    ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
+                 OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
+                 OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
+    ofn->lpstrDefExt = NULL;
+    ofn->lpfnHook = export_specified_packets_file_hook_proc;
+    ofn->lpTemplateName = _T("WIRESHARK_EXPORT_SPECIFIED_PACKETS_FILENAME_TEMPLATE");
+
+    gsfn_ok = GetSaveFileName(ofn);
+
+    if (gsfn_ok) {
+        g_string_printf(file_name, "%s", utf_16to8(file_name16));
+        /* What file format was specified? */
+        *file_type = g_array_index(savable_file_types, int, ofn->nFilterIndex - 1);
+        *compressed = g_compressed;
+    } else {
+        /* User cancelled or closed the dialog, or an error occurred. */
+        if (CommDlgExtendedError() != 0) {
+            /* XXX - pop up some error here. FNERR_INVALIDFILENAME
+             * might be a user error; if so, they should know about
+             * it. For now we force a do-over.
+             */
+            g_string_truncate(file_name, 0);
+            gsfn_ok = TRUE;
         }
     }
+
     g_sf_hwnd = NULL;
+    g_range = NULL;
+    g_array_free(savable_file_types, TRUE);
     g_free( (void *) ofn->lpstrFilter);
     g_free( (void *) ofn);
+    return gsfn_ok;
 }
 
 
-void
-win32_merge_file (HWND h_wnd) {
+gboolean
+win32_merge_file (HWND h_wnd, GString *file_name, GString *display_filter, int *merge_type) {
     OPENFILENAME *ofn;
-    TCHAR       file_name[MAX_PATH] = _T("");
-    char       *dirname;
-    cf_status_t merge_status = CF_ERROR;
-    char       *in_filenames[2];
-    int         err;
-    char       *tmpname;
-    dfilter_t  *dfp;
-    int         ofnsize;
+    TCHAR         file_name16[MAX_PATH] = _T("");
+    int           ofnsize;
+    gboolean gofn_ok;
 #if (_MSC_VER >= 1500)
     OSVERSIONINFO osvi;
 #endif
 
+    if (!file_name || !display_filter || !merge_type)
+        return FALSE;
+
+    if (file_name->len > 0) {
+        StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
+    }
+
+    if (display_filter->len > 0) {
+        g_dfilter_str = g_strdup(display_filter->str);
+    } else if (g_dfilter_str) {
+        g_free(g_dfilter_str);
+        g_dfilter_str = NULL;
+    }
+
     /* see OPENFILENAME comment in win32_open_file */
 #if (_MSC_VER >= 1500)
     SecureZeroMemory(&osvi, sizeof(OSVERSIONINFO));
@@ -438,16 +555,12 @@ win32_merge_file (HWND h_wnd) {
 
     ofn->lStructSize = ofnsize;
     ofn->hwndOwner = h_wnd;
-#if (_MSC_VER <= 1200)
-    ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
-#else
     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
-#endif
-    ofn->lpstrFilter = build_file_type_list(FALSE /*!save*/, NULL);
+    ofn->lpstrFilter = build_file_open_type_list();
     ofn->lpstrCustomFilter = NULL;
     ofn->nMaxCustFilter = 0;
     ofn->nFilterIndex = FILE_MERGE_DEFAULT;
-    ofn->lpstrFile = file_name;
+    ofn->lpstrFile = file_name16;
     ofn->nMaxFile = MAX_PATH;
     ofn->lpstrFileTitle = NULL;
     ofn->nMaxFileTitle = 0;
@@ -464,77 +577,36 @@ win32_merge_file (HWND h_wnd) {
     ofn->lpfnHook = merge_file_hook_proc;
     ofn->lpTemplateName = _T("WIRESHARK_MERGEFILENAME_TEMPLATE");
 
-    if (GetOpenFileName(ofn)) {
-        filetype = cfile.cd_t;
-        g_free( (void *) ofn->lpstrFilter);
-        g_free( (void *) ofn);
+    gofn_ok = GetOpenFileName(ofn);
 
-        /* merge or append the two files */
+    if (gofn_ok) {
+        g_string_printf(file_name, "%s", utf_16to8(file_name16));
+        g_string_printf(display_filter, "%s", g_dfilter_str ? g_dfilter_str : "");
 
-        tmpname = NULL;
-        switch (merge_action) {
+        switch (g_merge_action) {
             case merge_append:
-                /* append file */
-                in_filenames[0] = cfile.filename;
-                in_filenames[1] = utf_16to8(file_name);
-                merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, TRUE);
+                *merge_type = 1;
                 break;
             case merge_chrono:
-                /* chonological order */
-                in_filenames[0] = cfile.filename;
-                in_filenames[1] = utf_16to8(file_name);
-                merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, FALSE);
+                *merge_type = 0;
                 break;
             case merge_prepend:
-                /* prepend file */
-                in_filenames[0] = utf_16to8(file_name);
-                in_filenames[1] = cfile.filename;
-                merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, TRUE);
+                *merge_type = -1;
                 break;
             default:
                 g_assert_not_reached();
         }
-
-        if(merge_status != CF_OK) {
-            /* merge failed */
-            g_free(tmpname);
-            return;
-        }
-
-        cf_close(&cfile);
-
-        /* Try to open the merged capture file. */
-        if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) {
-            /* We couldn't open it; don't dismiss the open dialog box,
-               just leave it around so that the user can, after they
-               dismiss the alert box popped up for the open error,
-               try again. */
-            return;
-        }
-
-        /* apply our filter */
-        if (dfilter_compile(dfilter_str, &dfp)) {
-            cf_set_rfcode(&cfile, dfp);
-        }
-
-        switch (cf_read(&cfile, FALSE)) {
-            case CF_READ_OK:
-            case CF_READ_ERROR:
-                dirname = get_dirname(utf_16to8(file_name));
-                set_last_open_dir(dirname);
-                menu_name_resolution_changed();
-                break;
-            case CF_READ_ABORTED:
-                break;
-        }
-    } else {
-        g_free( (void *) ofn->lpstrFilter);
-        g_free( (void *) ofn);
     }
+
+    g_free( (void *) ofn->lpstrFilter);
+    g_free( (void *) ofn);
+    g_free(g_dfilter_str);
+    g_dfilter_str = NULL;
+    return gofn_ok;
 }
 
 void
-win32_export_file(HWND h_wnd, export_type_e export_type) {
+win32_export_file(HWND h_wnd, capture_file *cf, export_type_e export_type) {
     OPENFILENAME     *ofn;
     TCHAR             file_name[MAX_PATH] = _T("");
     char             *dirname;
@@ -561,11 +633,7 @@ win32_export_file(HWND h_wnd, export_type_e export_type) {
 
     ofn->lStructSize = ofnsize;
     ofn->hwndOwner = h_wnd;
-#if (_MSC_VER <= 1200)
-    ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
-#else
     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
-#endif
     ofn->lpstrFilter = FILE_TYPES_EXPORT;
     ofn->lpstrCustomFilter = NULL;
     ofn->nMaxCustFilter = 0;
@@ -589,6 +657,7 @@ win32_export_file(HWND h_wnd, export_type_e export_type) {
     print_args.to_file             = TRUE;
     print_args.cmd                 = NULL;
     print_args.print_summary       = TRUE;
+    print_args.print_col_headings  = TRUE;
     print_args.print_dissections   = print_dissections_as_displayed;
     print_args.print_hex           = FALSE;
     print_args.print_formfeed      = FALSE;
@@ -603,7 +672,7 @@ win32_export_file(HWND h_wnd, export_type_e export_type) {
                     g_free( (void *) ofn);
                     return;
                 }
-                status = cf_print_packets(&cfile, &print_args);
+                status = cf_print_packets(cf, &print_args);
                 break;
             case export_type_ps:        /* PostScript (r) */
                 print_args.stream = print_stream_ps_new(TRUE, print_args.file);
@@ -612,19 +681,19 @@ win32_export_file(HWND h_wnd, export_type_e export_type) {
                     g_free( (void *) ofn);
                     return;
                 }
-                status = cf_print_packets(&cfile, &print_args);
+                status = cf_print_packets(cf, &print_args);
                 break;
             case export_type_csv:       /* CSV */
-                status = cf_write_csv_packets(&cfile, &print_args);
+                status = cf_write_csv_packets(cf, &print_args);
                 break;
             case export_type_carrays:   /* C Arrays */
-                status = cf_write_carrays_packets(&cfile, &print_args);
+                status = cf_write_carrays_packets(cf, &print_args);
                 break;
             case export_type_psml:      /* PSML */
-                status = cf_write_psml_packets(&cfile, &print_args);
+                status = cf_write_psml_packets(cf, &print_args);
                 break;
             case export_type_pdml:      /* PDML */
-                status = cf_write_pdml_packets(&cfile, &print_args);
+                status = cf_write_pdml_packets(cf, &print_args);
                 break;
             default:
                 g_free( (void *) ofn);
@@ -685,11 +754,7 @@ win32_export_raw_file(HWND h_wnd) {
 
     ofn->lStructSize = ofnsize;
     ofn->hwndOwner = h_wnd;
-#if (_MSC_VER <= 1200)
-    ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
-#else
     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
-#endif
     ofn->lpstrFilter = FILE_TYPES_RAW;
     ofn->lpstrCustomFilter = NULL;
     ofn->nMaxCustFilter = 0;
@@ -746,7 +811,7 @@ win32_export_sslkeys_file(HWND h_wnd) {
     OPENFILENAME *ofn;
     TCHAR         file_name[MAX_PATH] = _T("");
     char         *dirname;
-    StringInfo   *keylist;
+    gchar        *keylist;
     char         *file_name8;
     int           fd;
     int           ofnsize;
@@ -755,7 +820,7 @@ win32_export_sslkeys_file(HWND h_wnd) {
     OSVERSIONINFO osvi;
 #endif
 
-    keylist_size = g_hash_table_size(ssl_session_hash);
+    keylist_size = ssl_session_key_count();
     if (keylist_size==0) {
         /* This shouldn't happen */
         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No SSL Session Keys to export.");
@@ -779,11 +844,7 @@ win32_export_sslkeys_file(HWND h_wnd) {
 
     ofn->lStructSize = ofnsize;
     ofn->hwndOwner = h_wnd;
-#if (_MSC_VER <= 1200)
-    ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
-#else
     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
-#endif
     ofn->lpstrFilter = FILE_TYPES_SSLKEYS;
     ofn->lpstrCustomFilter = NULL;
     ofn->nMaxCustFilter = 0;
@@ -805,7 +866,7 @@ win32_export_sslkeys_file(HWND h_wnd) {
     if (GetSaveFileName(ofn)) {
         g_free( (void *) ofn);
         file_name8 = utf_16to8(file_name);
-        keylist = ssl_export_sessions(ssl_session_hash);
+        keylist = ssl_export_sessions();
         fd = ws_open(file_name8, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
         if (fd == -1) {
             open_failure_alert_box(file_name8, errno, TRUE);
@@ -816,7 +877,7 @@ win32_export_sslkeys_file(HWND h_wnd) {
          * Thanks, Microsoft, for not using size_t for the third argument to
          * _write().  Presumably this string will be <= 4GiB long....
          */
-        if (ws_write(fd, keylist->data, (unsigned int)strlen(keylist->data)) < 0) {
+        if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
             write_failure_alert_box(file_name8, errno);
             ws_close(fd);
             g_free(keylist);
@@ -864,11 +925,7 @@ win32_export_color_file(HWND h_wnd, gpointer filter_list) {
 
     ofn->lStructSize = ofnsize;
     ofn->hwndOwner = h_wnd;
-#if (_MSC_VER <= 1200)
-    ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
-#else
     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
-#endif
     ofn->lpstrFilter = FILE_TYPES_COLOR;
     ofn->lpstrCustomFilter = NULL;
     ofn->nMaxCustFilter = 0;
@@ -886,7 +943,7 @@ win32_export_color_file(HWND h_wnd, gpointer filter_list) {
     ofn->lpfnHook = NULL;
     ofn->lpTemplateName = NULL;
 
-    filetype = cfile.cd_t;
+    g_filetype = cfile.cd_t;
 
     /* XXX - Support marked filters */
     if (GetSaveFileName(ofn)) {
@@ -929,11 +986,7 @@ win32_import_color_file(HWND h_wnd, gpointer color_filters) {
 
     ofn->lStructSize = ofnsize;
     ofn->hwndOwner = h_wnd;
-#if (_MSC_VER <= 1200)
-    ofn->hInstance = (HINSTANCE) GetWindowLong(h_wnd, GWL_HINSTANCE);
-#else
     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
-#endif
     ofn->lpstrFilter = FILE_TYPES_COLOR;
     ofn->lpstrCustomFilter = NULL;
     ofn->nMaxCustFilter = 0;
@@ -981,10 +1034,20 @@ print_update_dynamic(HWND dlg_hwnd, print_args_t *args) {
     HWND cur_ctrl;
 
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_SUMMARY_CB);
-    if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
+    if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
         args->print_summary = TRUE;
-    else
+        cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_COL_HEADINGS_CB);
+        EnableWindow(cur_ctrl, TRUE);
+        if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
+            args->print_col_headings = TRUE;
+        else
+            args->print_col_headings = FALSE;
+    } else {
         args->print_summary = FALSE;
+        args->print_col_headings = FALSE;
+        cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_COL_HEADINGS_CB);
+        EnableWindow(cur_ctrl, FALSE);
+    }
 
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_CB);
     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
@@ -1026,9 +1089,11 @@ static void
 format_handle_wm_initdialog(HWND dlg_hwnd, print_args_t *args) {
     HWND cur_ctrl;
 
-    /* Set the "Packet summary" box */
+    /* Set the "Packet summary" and "Include column headings" boxes */
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_SUMMARY_CB);
     SendMessage(cur_ctrl, BM_SETCHECK, args->print_summary, 0);
+    cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_COL_HEADINGS_CB);
+    SendMessage(cur_ctrl, BM_SETCHECK, args->print_col_headings, 0);
 
     /* Set the "Packet details" box */
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_CB);
@@ -1071,7 +1136,7 @@ format_handle_wm_initdialog(HWND dlg_hwnd, print_args_t *args) {
 /* If preview_file is NULL, disable the elements.  If not, enable and
  * show the preview info. */
 static gboolean
-preview_set_filename(HWND of_hwnd, gchar *preview_file) {
+preview_set_file_info(HWND of_hwnd, gchar *preview_file) {
     HWND        cur_ctrl;
     int         i;
     gboolean    enable = FALSE;
@@ -1093,125 +1158,134 @@ preview_set_filename(HWND of_hwnd, gchar *preview_file) {
     double      cur_time;
     gboolean    is_breaked = FALSE;
 
-    if (preview_file != NULL && strlen(preview_file) > 0) {
-        enable = TRUE;
-    }
-
-    for (i = EWFD_PT_FILENAME; i <= EWFD_PTX_ELAPSED; i++) {
+    for (i = EWFD_PTX_FORMAT; i <= EWFD_PTX_ELAPSED; i++) {
         cur_ctrl = GetDlgItem(of_hwnd, i);
         if (cur_ctrl) {
-            EnableWindow(cur_ctrl, enable);
+            EnableWindow(cur_ctrl, FALSE);
         }
     }
 
-    for (i = EWFD_PTX_FILENAME; i <= EWFD_PTX_ELAPSED; i++) {
+    for (i = EWFD_PTX_FORMAT; i <= EWFD_PTX_ELAPSED; i++) {
         cur_ctrl = GetDlgItem(of_hwnd, i);
         if (cur_ctrl) {
             SetWindowText(cur_ctrl, _T("-"));
         }
     }
 
-    if (enable) {
-        cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FILENAME);
-        SetWindowText(cur_ctrl, utf_8to16(get_basename(preview_file)));
-
-        cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
-        wth = wtap_open_offline(preview_file, &err, &err_info, TRUE);
-        if (cur_ctrl && wth == NULL) {
-            if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
-                SetWindowText(cur_ctrl, _T("unknown file format"));
-            } else {
-                SetWindowText(cur_ctrl, _T("error opening file"));
-            }
-            return FALSE;
-        }
+    if (preview_file == NULL || strlen(preview_file) < 1) {
+        return FALSE;
+    }
 
-        /* size */
-        filesize = wtap_file_size(wth, &err);
-        utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%" G_GINT64_FORMAT " bytes", filesize);
-        cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_SIZE);
-        SetWindowText(cur_ctrl, string_buff);
+    /* Format: directory */
+    cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
+    if (test_for_directory(preview_file) == EISDIR) {
+        SetWindowText(cur_ctrl, _T("directory"));
+        return FALSE;
+    }
 
-        /* type */
-        cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
-        SetWindowText(cur_ctrl, utf_8to16(wtap_file_type_string(wtap_file_type(wth))));
-
-        time(&time_preview);
-        while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
-            phdr = wtap_phdr(wth);
-            cur_time = nstime_to_sec( (const nstime_t *) &phdr->ts );
-            if(packet == 0) {
-                start_time  = cur_time;
-                stop_time = cur_time;
-            }
-            if (cur_time < start_time) {
-                start_time = cur_time;
-            }
-            if (cur_time > stop_time){
-                stop_time = cur_time;
-            }
-            packet++;
-            if(packet%100 == 0) {
-                time(&time_current);
-                if(time_current-time_preview >= (time_t) prefs.gui_fileopen_preview) {
-                    is_breaked = TRUE;
-                    break;
-                }
-            }
+    wth = wtap_open_offline(preview_file, &err, &err_info, TRUE);
+    if (cur_ctrl && wth == NULL) {
+        if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
+            SetWindowText(cur_ctrl, _T("unknown file format"));
+        } else {
+            SetWindowText(cur_ctrl, _T("error opening file"));
         }
+        return FALSE;
+    }
 
-        if(err != 0) {
-            _snwprintf(string_buff, PREVIEW_STR_MAX, _T("error after reading %u packets"), packet);
-            cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_PACKETS);
-            SetWindowText(cur_ctrl, string_buff);
-            wtap_close(wth);
-            return TRUE;
+    /* Success! */
+    for (i = EWFD_PT_FORMAT; i <= EWFD_PTX_ELAPSED; i++) {
+        cur_ctrl = GetDlgItem(of_hwnd, i);
+        if (cur_ctrl) {
+            EnableWindow(cur_ctrl, TRUE);
         }
+    }
 
-        /* packet count */
-        if(is_breaked) {
-            _snwprintf(string_buff, PREVIEW_STR_MAX, _T("more than %u packets (preview timeout)"), packet);
-        } else {
-            _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%u"), packet);
+    /* Format */
+    cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
+    SetWindowText(cur_ctrl, utf_8to16(wtap_file_type_string(wtap_file_type(wth))));
+
+    /* Size */
+    filesize = wtap_file_size(wth, &err);
+    utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%" G_GINT64_FORMAT " bytes", filesize);
+    cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_SIZE);
+    SetWindowText(cur_ctrl, string_buff);
+
+    time(&time_preview);
+    while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
+        phdr = wtap_phdr(wth);
+        cur_time = nstime_to_sec( (const nstime_t *) &phdr->ts );
+        if(packet == 0) {
+            start_time  = cur_time;
+            stop_time = cur_time;
         }
-        cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_PACKETS);
-        SetWindowText(cur_ctrl, string_buff);
-
-        /* first packet */
-        ti_time = (long)start_time;
-        ti_tm = localtime( &ti_time );
-        if(ti_tm) {
-            _snwprintf(string_buff, PREVIEW_STR_MAX,
-                     _T("%04d-%02d-%02d %02d:%02d:%02d"),
-                     ti_tm->tm_year + 1900,
-                     ti_tm->tm_mon + 1,
-                     ti_tm->tm_mday,
-                     ti_tm->tm_hour,
-                     ti_tm->tm_min,
-                     ti_tm->tm_sec);
-        } else {
-            _snwprintf(string_buff, PREVIEW_STR_MAX, _T("?"));
+        if (cur_time < start_time) {
+            start_time = cur_time;
         }
-        cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FIRST_PKT);
-        SetWindowText(cur_ctrl, string_buff);
-
-        /* elapsed time */
-        elapsed_time = (unsigned int)(stop_time-start_time);
-        if(elapsed_time/86400) {
-            _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%02u days %02u:%02u:%02u"),
-            elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
-        } else {
-            _snwprintf(string_buff, PREVIEW_STR_MAX, _T("%02u:%02u:%02u"),
-            elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
+        if (cur_time > stop_time){
+            stop_time = cur_time;
         }
-        if(is_breaked) {
-            _snwprintf(string_buff, PREVIEW_STR_MAX, _T("unknown"));
+        packet++;
+        if(packet%100 == 0) {
+            time(&time_current);
+            if(time_current-time_preview >= (time_t) prefs.gui_fileopen_preview) {
+                is_breaked = TRUE;
+                break;
+            }
         }
-        cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_ELAPSED);
-        SetWindowText(cur_ctrl, string_buff);
+    }
 
+    if(err != 0) {
+        StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("error after reading %u packets"), packet);
+        cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_PACKETS);
+        SetWindowText(cur_ctrl, string_buff);
         wtap_close(wth);
+        return TRUE;
+    }
+
+    /* Packets */
+    if(is_breaked) {
+        StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("more than %u packets (preview timeout)"), packet);
+    } else {
+        StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%u"), packet);
+    }
+    cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_PACKETS);
+    SetWindowText(cur_ctrl, string_buff);
+
+    /* First packet */
+    ti_time = (long)start_time;
+    ti_tm = localtime( &ti_time );
+    if(ti_tm) {
+        StringCchPrintf(string_buff, PREVIEW_STR_MAX,
+                 _T("%04d-%02d-%02d %02d:%02d:%02d"),
+                 ti_tm->tm_year + 1900,
+                 ti_tm->tm_mon + 1,
+                 ti_tm->tm_mday,
+                 ti_tm->tm_hour,
+                 ti_tm->tm_min,
+                 ti_tm->tm_sec);
+    } else {
+        StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("?"));
+    }
+    cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FIRST_PKT);
+    SetWindowText(cur_ctrl, string_buff);
+
+    /* Elapsed time */
+    elapsed_time = (unsigned int)(stop_time-start_time);
+    if(elapsed_time/86400) {
+        StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%02u days %02u:%02u:%02u"),
+        elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
+    } else {
+        StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%02u:%02u:%02u"),
+        elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
     }
+    if(is_breaked) {
+        StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("unknown"));
+    }
+    cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_ELAPSED);
+    SetWindowText(cur_ctrl, string_buff);
+
+    wtap_close(wth);
 
     return TRUE;
 
@@ -1273,21 +1347,17 @@ filter_tb_syntax_check(HWND hwnd, TCHAR *filter_text) {
         if (dfp != NULL)
             dfilter_free(dfp);
         /* Valid (light green) */
-        SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, 0x00afffaf);
+        SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, RGB(0xe4, 0xff, 0xc7)); /* tango_chameleon_1 */
     } else {
         /* Invalid (light red) */
-        SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, 0x00afafff);
+        SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, RGB(0xff, 0xcc, 0xcc)); /* tango_scarlet_red_1 */
     }
 
     if (strval) g_free(strval);
 }
 
 
-#if (_MSC_VER <= 1200)
-static UINT CALLBACK
-#else
 static UINT_PTR CALLBACK
-#endif
 open_file_hook_proc(HWND of_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     HWND      cur_ctrl, parent;
     OFNOTIFY *notify = (OFNOTIFY *) l_param;
@@ -1296,51 +1366,55 @@ open_file_hook_proc(HWND of_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     switch(msg) {
         case WM_INITDIALOG:
             /* Retain the filter text, and fill it in. */
-            if(dfilter_str != NULL) {
+            if(g_dfilter_str != NULL) {
                 cur_ctrl = GetDlgItem(of_hwnd, EWFD_FILTER_EDIT);
-                SetWindowText(cur_ctrl, utf_8to16(dfilter_str));
+                SetWindowText(cur_ctrl, utf_8to16(g_dfilter_str));
             }
 
             /* Fill in our resolution values */
             cur_ctrl = GetDlgItem(of_hwnd, EWFD_MAC_NR_CB);
-            SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags & RESOLV_MAC, 0);
+            SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags.mac_name, 0);
             cur_ctrl = GetDlgItem(of_hwnd, EWFD_NET_NR_CB);
-            SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags & RESOLV_NETWORK, 0);
+            SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags.network_name, 0);
             cur_ctrl = GetDlgItem(of_hwnd, EWFD_TRANS_NR_CB);
-            SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags & RESOLV_TRANSPORT, 0);
+            SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags.transport_name, 0);
+            cur_ctrl = GetDlgItem(of_hwnd, EWFD_EXTERNAL_NR_CB);
+            SendMessage(cur_ctrl, BM_SETCHECK, gbl_resolv_flags.use_external_net_name_resolver, 0);
 
-            preview_set_filename(of_hwnd, NULL);
+            preview_set_file_info(of_hwnd, NULL);
             break;
         case WM_NOTIFY:
             switch (notify->hdr.code) {
                 case CDN_FILEOK:
                     /* Fetch the read filter */
                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_FILTER_EDIT);
-                    if (dfilter_str)
-                        g_free(dfilter_str);
-                    dfilter_str = filter_tb_get(cur_ctrl);
+                    if (g_dfilter_str)
+                        g_free(g_dfilter_str);
+                    g_dfilter_str = filter_tb_get(cur_ctrl);
 
                     /* Fetch our resolution values */
-                    gbl_resolv_flags = prefs.name_resolve & RESOLV_CONCURRENT;
                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_MAC_NR_CB);
                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
-                        gbl_resolv_flags |= RESOLV_MAC;
+                        gbl_resolv_flags.mac_name = TRUE;
                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_NET_NR_CB);
                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
-                        gbl_resolv_flags |= RESOLV_NETWORK;
+                        gbl_resolv_flags.network_name = TRUE;
                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_TRANS_NR_CB);
                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
-                        gbl_resolv_flags |= RESOLV_TRANSPORT;
+                        gbl_resolv_flags.transport_name = TRUE;
+                    cur_ctrl = GetDlgItem(of_hwnd, EWFD_EXTERNAL_NR_CB);
+                    if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
+                        gbl_resolv_flags.use_external_net_name_resolver = TRUE;
                     break;
                 case CDN_SELCHANGE:
                     /* This _almost_ works correctly. We need to handle directory
                        selections, etc. */
                     parent = GetParent(of_hwnd);
-                    CommDlg_OpenSave_GetSpec(parent, sel_name, MAX_PATH);
-                    preview_set_filename(of_hwnd, utf_16to8(sel_name));
+                    CommDlg_OpenSave_GetFilePath(parent, sel_name, MAX_PATH);
+                    preview_set_file_info(of_hwnd, utf_16to8(sel_name));
                     break;
                 case CDN_HELP:
-                    topic_cb(NULL, HELP_OPEN_WIN32_DIALOG);
+                    topic_action(HELP_OPEN_WIN32_DIALOG);
                     break;
                 default:
                     break;
@@ -1371,22 +1445,9 @@ open_file_hook_proc(HWND of_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     return 0;
 }
 
-/* XXX - Copied verbatim from ui/gtk/capture_file_dlg.c.  Perhaps it
- * should be in wiretap instead?
- */
-
-static gboolean
-can_save_with_wiretap(int ft)
-{
-    /* To save a file with Wiretap, Wiretap has to handle that format,
-     and its code to handle that format must be able to write a file
-     with this file's encapsulation type. */
-    return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
-}
-
 /* Generate a list of the file types we can save this file as.
 
-   "filetype" is the type it has now.
+   "g_filetype" is the type it has now.
 
    "encap" is the encapsulation for its packets (which could be
    "unknown" or "per-packet").
@@ -1398,123 +1459,95 @@ can_save_with_wiretap(int ft)
 
    The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
 */
+static void
+append_file_type(GArray *sa, int ft)
+{
+    GString* pattern_str = g_string_new("");
+    GString* description_str = g_string_new("");
+    gchar sep;
+    GSList *extensions_list, *extension;
+    TCHAR *str16;
+    guint16 zero = 0;
 
-static int
-file_type_from_list_index(gboolean save, int index) {
-    int   ft;
-    int curr_index;
-
-    /* Check all file types. */
-    curr_index = 0;
-    for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
-        if (save && (!packet_range_process_all(&g_range) || ft != cfile.cd_t)) {
-            /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
-            if (!can_save_with_wiretap(ft))
-                continue;       /* We can't. */
+    extensions_list = wtap_get_file_extensions_list(ft, TRUE);
+    if (extensions_list == NULL) {
+        /* This file type doesn't have any particular extension
+           conventionally used for it, so we'll just use "*.*"
+           as the pattern; on Windows, that matches all file names
+           - even those with no extension -  so we don't need to
+           worry about compressed file extensions.  (It does not
+           do so on UN*X; the right pattern on UN*X would just
+           be "*".) */
+           g_string_printf(pattern_str, "*.*");
+    } else {
+        /* Construct the list of patterns. */
+        g_string_printf(pattern_str, "");
+        sep = '\0';
+        for (extension = extensions_list; extension != NULL;
+             extension = g_slist_next(extension)) {
+            if (sep != '\0')
+                g_string_append_c(pattern_str, sep);
+            g_string_append_printf(pattern_str, "*.%s", (char *)extension->data);
+            sep = ';';
         }
+        wtap_free_file_extensions_list(extensions_list);
+    }
 
-        /* OK, we can write it out in this type. */
-        if(wtap_file_type_string(ft) == NULL) {
-            continue;
-        }
+    /* Construct the description. */
+    g_string_printf(description_str, "%s (%s)", wtap_file_type_string(ft),
+                    pattern_str->str);
+    str16 = utf_8to16(description_str->str);
+    sa = g_array_append_vals(sa, str16, (guint) strlen(description_str->str));
+    sa = g_array_append_val(sa, zero);
 
-        curr_index++;
-        if(curr_index == index) {
-            return ft;
-        }
-    }
+    str16 = utf_8to16(pattern_str->str);
+    sa = g_array_append_vals(sa, str16, (guint) strlen(pattern_str->str));
+    sa = g_array_append_val(sa, zero);
 
-    return -1;
 }
 
-
 static TCHAR *
-build_file_type_list(gboolean save, int *item_to_select) {
-    int   ft;
-    guint index;
-    GString* pattern_str = g_string_new("");
-    GString* description_str = g_string_new("");
-    gchar sep;
-    GSList *extensions_list, *extension;
+build_file_open_type_list(void) {
     TCHAR *str16;
+    int   ft;
     GArray* sa = g_array_new(FALSE /*zero_terminated*/, FALSE /*clear_*/,2 /*element_size*/);
     guint16 zero = 0;
 
 
-    /* Default to the first supported file type, if the file's current
-       type isn't supported. */
-    if(item_to_select) {
-        if(save) {
-            *item_to_select = FILE_SAVE_DEFAULT;
-        } else {
-            *item_to_select = FILE_OPEN_DEFAULT;
-        }
-    }
-
-    /* append the "All Files" entry */
-    if (!save) {
-        str16 = utf_8to16("All Files (*.*)");
-        sa = g_array_append_vals(sa, str16, (guint) strlen("All Files (*.*)"));
-        sa = g_array_append_val(sa, zero);
-        str16 = utf_8to16("*.*");
-        sa = g_array_append_vals(sa, str16, (guint) strlen("*.*"));
-        sa = g_array_append_val(sa, zero);
-    }
+    /* Add the "All Files" entry. */
+    str16 = utf_8to16("All Files (*.*)");
+    sa = g_array_append_vals(sa, str16, (guint) strlen("All Files (*.*)"));
+    sa = g_array_append_val(sa, zero);
+    str16 = utf_8to16("*.*");
+    sa = g_array_append_vals(sa, str16, (guint) strlen("*.*"));
+    sa = g_array_append_val(sa, zero);
 
-    /* Check all file types. */
-    index = 1;  /* the index is one based! */
+    /* Include all the file types Wireshark supports. */
     for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
-        if (save && (!packet_range_process_all(&g_range) || ft != cfile.cd_t)) {
-            /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
-            if (!can_save_with_wiretap(ft))
-                continue;       /* We can't. */
-        }
+        if (ft == WTAP_FILE_UNKNOWN)
+            continue;  /* not a real file type */
 
-        /* OK, we can write it out in this type. */
-        extensions_list = wtap_get_file_extensions_list(ft);
-        if (extensions_list == NULL) {
-            /* This file type doesn't have any particular extension
-               conventionally used for it, so we'll just use "*.*"
-               as the pattern; on Windows, that matches all file names
-              - even those with no extension -  so we don't need to
-              worry about compressed file extensions.  (It does not
-              do so on UN*X; the right pattern on UN*X would just
-              be "*".) */
-            g_string_printf(pattern_str, "*.*");
-        } else {
-            /* Construct the list of patterns. */
-            g_string_printf(pattern_str, "");
-            sep = '\0';
-            for (extension = extensions_list; extension != NULL;
-                 extension = g_slist_next(extension)) {
-                if (sep != '\0')
-                    g_string_append_c(pattern_str, sep);
-                g_string_append_printf(pattern_str, "*.%s", (char *)extension->data);
-                sep = ';';
-            }
-        }
+        append_file_type(sa, ft);
+    }
 
-        /* Construct the description. */
-        g_string_printf(description_str, "%s (%s)", wtap_file_type_string(ft),
-                        pattern_str->str);
-        str16 = utf_8to16(description_str->str);
-        sa = g_array_append_vals(sa, str16, (guint) strlen(description_str->str));
-        sa = g_array_append_val(sa, zero);
+    /* terminate the array */
+    sa = g_array_append_val(sa, zero);
 
-        str16 = utf_8to16(pattern_str->str);
-        sa = g_array_append_vals(sa, str16, (guint) strlen(pattern_str->str));
-        sa = g_array_append_val(sa, zero);
+    return (TCHAR *) g_array_free(sa, FALSE /*free_segment*/);
+}
 
-        wtap_free_file_extensions_list(extensions_list);
+static TCHAR *
+build_file_save_type_list(GArray *savable_file_types) {
+    guint i;
+    int   ft;
+    GArray* sa = g_array_new(FALSE /*zero_terminated*/, FALSE /*clear_*/,2 /*element_size*/);
+    guint16 zero = 0;
 
-        if (ft == cfile.cd_t && item_to_select != NULL) {
-            /* Default to the same format as the file, if it's supported. */
-            *item_to_select = index;
-        }
-        index++;
+    /* Get only the file types as which we can save this file. */
+    for (i = 0; i < savable_file_types->len; i++) {
+        ft = g_array_index(savable_file_types, int, i);
+        append_file_type(sa, ft);
     }
-    g_string_free(pattern_str, TRUE);
-    g_string_free(description_str, TRUE);
 
     /* terminate the array */
     sa = g_array_append_val(sa, zero);
@@ -1542,9 +1575,12 @@ build_file_format_list(HWND sf_hwnd) {
     /* Check all file types. */
     index = 0;
     for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
-        if (!packet_range_process_all(&g_range) || ft != cfile.cd_t) {
+        if (ft == WTAP_FILE_UNKNOWN)
+            continue;  /* not a real file type */
+
+        if (!packet_range_process_all(g_range) || ft != cfile.cd_t) {
             /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
-            if (!can_save_with_wiretap(ft))
+            if (!wtap_can_save_with_wiretap(ft, cfile.linktypes))
                 continue;       /* We can't. */
         }
 
@@ -1557,7 +1593,7 @@ build_file_format_list(HWND sf_hwnd) {
         SendMessage(format_cb, CB_ADDSTRING, 0, (LPARAM) utf_8to16(s));
         g_free(s);
         SendMessage(format_cb, CB_SETITEMDATA, (LPARAM) index, (WPARAM) ft);
-        if (ft == filetype) {
+        if (ft == g_filetype) {
             /* Default to the same format as the file, if it's supported. */
             item_to_select = index;
         }
@@ -1568,12 +1604,7 @@ build_file_format_list(HWND sf_hwnd) {
 }
 #endif
 
-#define RANGE_TEXT_MAX 128
-#if (_MSC_VER <= 1200)
-static UINT CALLBACK
-#else
 static UINT_PTR CALLBACK
-#endif
 save_as_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     HWND           cur_ctrl;
     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
@@ -1583,18 +1614,122 @@ save_as_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
         case WM_INITDIALOG:
             g_sf_hwnd = sf_hwnd;
 
-            /* Default to saving all packets, in the file's current format. */
-            filetype = cfile.cd_t;
+            /* Default to saving in the file's current format. */
+            g_filetype = cfile.cd_t;
 
-            /* init the packet range */
-            packet_range_init(&g_range);
-            /* default to displayed packets */
-            g_range.process_filtered   = TRUE;
+            /* Fill in the file format list */
+            /*build_file_format_list(sf_hwnd);*/
+            /* Fill in the compression checkbox */
+            cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
+            SendMessage(cur_ctrl, BM_SETCHECK, g_compressed, 0);
+
+            break;
+        case WM_COMMAND:
+            cur_ctrl = (HWND) l_param;
+
+            switch (w_param) {
+#if 0
+                case (CBN_SELCHANGE << 16) | EWFD_FILE_TYPE_COMBO:
+                    index = SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0);
+                    if (index != CB_ERR) {
+                        new_filetype = SendMessage(cur_ctrl, CB_GETITEMDATA, (WPARAM) index, 0);
+                        if (new_filetype != CB_ERR) {
+                            if (g_filetype != new_filetype) {
+                                if (wtap_can_save_with_wiretap(new_filetype, cfile.linktypes)) {
+                                    cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
+                                    EnableWindow(cur_ctrl, TRUE);
+                                    cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
+                                    EnableWindow(cur_ctrl, TRUE);
+                                } else {
+                                    cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
+                                    SendMessage(cur_ctrl, BM_SETCHECK, 0, 0);
+                                    EnableWindow(cur_ctrl, FALSE);
+                                    cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
+                                    EnableWindow(cur_ctrl, FALSE);
+                                }
+                                g_filetype = new_filetype;
+                                cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
+                                if (wtap_dump_can_compress(file_type) {
+                                    EnableWindow(cur_ctrl);
+                                } else {
+                                    g_compressed = FALSE;
+                                    DisableWindow(cur_ctrl);
+                                }
+                                SendMessage(cur_ctrl, BM_SETCHECK, g_compressed, 0);
+
+                            }
+                        }
+                    }
+                    break;
+#endif
+                default:
+                    break;
+            }
+            break;
+        case WM_NOTIFY:
+            switch (notify->hdr.code) {
+                case CDN_HELP:
+                    topic_action(HELP_SAVE_WIN32_DIALOG);
+                    break;
+                case CDN_FILEOK: {
+                    HWND   parent;
+                    char  *file_name8;
+
+                    /* Fetch our compression value */
+                    cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
+                    if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
+                        g_compressed = TRUE;
+                    else
+                        g_compressed = FALSE;
+
+                    /* Check if we're trying to overwrite the currently open file */
+                    parent = GetParent(sf_hwnd);
+                    file_name8 = utf_16to8(notify->lpOFN->lpstrFile);
+                    if (files_identical(cfile.filename, file_name8)) {
+                        /* XXX: Is MessageBox the best way to pop up an error ? How to make text bold ? */
+                        gchar *str = g_strdup_printf(
+                            "Capture File \"%s\" identical to loaded file.\n\n"
+                            "Please choose a different filename.",
+                            file_name8);
+                        MessageBox( parent, utf_8to16(str), _T("Error"), MB_ICONERROR | MB_APPLMODAL | MB_OK);
+                        g_free(str);
+                        SetWindowLongPtr(sf_hwnd, DWLP_MSGRESULT, 1L); /* Don't allow ! */
+                        return 1;
+                    }
+                }
+                    break;
+                default:
+                    break;
+            }
+            break;
+        default:
+            break;
+    }
+    return 0;
+}
+
+#define RANGE_TEXT_MAX 128
+static UINT_PTR CALLBACK
+export_specified_packets_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
+    HWND           cur_ctrl;
+    OFNOTIFY      *notify = (OFNOTIFY *) l_param;
+    /*int            new_filetype, index;*/
+
+    switch(msg) {
+        case WM_INITDIALOG:
+            g_sf_hwnd = sf_hwnd;
+
+            /* Default to saving all packets, in the file's current format. */
+            g_filetype = cfile.cd_t;
 
             /* Fill in the file format list */
             /*build_file_format_list(sf_hwnd);*/
 
-            range_handle_wm_initdialog(sf_hwnd, &g_range);
+            range_handle_wm_initdialog(sf_hwnd, g_range);
+
+            /* Fill in the compression checkbox */
+            cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
+            SendMessage(cur_ctrl, BM_SETCHECK, g_compressed, 0);
 
             break;
         case WM_COMMAND:
@@ -1607,8 +1742,8 @@ save_as_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
                     if (index != CB_ERR) {
                         new_filetype = SendMessage(cur_ctrl, CB_GETITEMDATA, (WPARAM) index, 0);
                         if (new_filetype != CB_ERR) {
-                            if (filetype != new_filetype) {
-                                if (can_save_with_wiretap(new_filetype)) {
+                            if (g_filetype != new_filetype) {
+                                if (wtap_can_save_with_wiretap(new_filetype, cfile.linktypes)) {
                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
                                     EnableWindow(cur_ctrl, TRUE);
                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
@@ -1620,44 +1755,46 @@ save_as_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
                                     EnableWindow(cur_ctrl, FALSE);
                                 }
-                                filetype = new_filetype;
+                                g_filetype = new_filetype;
                             }
                         }
                     }
                     break;
 #endif
                 default:
-                    range_handle_wm_command(sf_hwnd, cur_ctrl, w_param, &g_range);
+                    range_handle_wm_command(sf_hwnd, cur_ctrl, w_param, g_range);
                     break;
             }
             break;
         case WM_NOTIFY:
             switch (notify->hdr.code) {
                 case CDN_HELP:
-                    topic_cb(NULL, HELP_SAVE_WIN32_DIALOG);
+                    topic_action(HELP_SAVE_WIN32_DIALOG);
                     break;
                 case CDN_FILEOK: {
                     HWND   parent;
-                    TCHAR  file_name16_selected[MAX_PATH];
-                    char  *file_name8_selected;
-                    int    selected_size;
+                    char  *file_name8;
 
-                    /* Check if trying to do 'save as' to the currently open file */
+                    /* Fetch our compression value */
+                    cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
+                    if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
+                        g_compressed = TRUE;
+                    else
+                        g_compressed = FALSE;
+
+                    /* Check if we're trying to overwrite the currently open file */
                     parent = GetParent(sf_hwnd);
-                    selected_size = CommDlg_OpenSave_GetSpec(parent, file_name16_selected, MAX_PATH);
-                    if (selected_size > 0) {
-                        file_name8_selected = utf_16to8(file_name16_selected);
-                        if (files_identical(cfile.filename, file_name8_selected)) {
-                            /* XXX: Is MessageBox the best way to pop up an error ? How to make text bold ? */
-                            gchar *str = g_strdup_printf(
-                                "Capture File \"%s\" identical to loaded file !!\n\n"
-                                "Please choose a different filename.",
-                                file_name8_selected);
-                            MessageBox( parent, utf_8to16(str), _T("Error"), MB_ICONERROR | MB_APPLMODAL | MB_OK);
-                            g_free(str);
-                            SetWindowLongPtr(sf_hwnd, DWLP_MSGRESULT, 1L); /* Don't allow ! */
-                            return 1;
-                        }
+                    file_name8 = utf_16to8(notify->lpOFN->lpstrFile);
+                    if (files_identical(cfile.filename, file_name8)) {
+                        /* XXX: Is MessageBox the best way to pop up an error ? How to make text bold ? */
+                        gchar *str = g_strdup_printf(
+                            "Capture File \"%s\" identical to loaded file.\n\n"
+                            "Please choose a different filename.",
+                            file_name8);
+                        MessageBox( parent, utf_8to16(str), _T("Error"), MB_ICONERROR | MB_APPLMODAL | MB_OK);
+                        g_free(str);
+                        SetWindowLongPtr(sf_hwnd, DWLP_MSGRESULT, 1L); /* Don't allow ! */
+                        return 1;
                     }
                 }
                     break;
@@ -1681,6 +1818,8 @@ range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
     TCHAR    static_val[STATIC_LABEL_CHARS];
     gint     selected_num;
     guint32  ignored_cnt = 0, displayed_ignored_cnt = 0;
+    guint32  displayed_cnt;
+    gboolean range_valid = TRUE;
 
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
@@ -1690,18 +1829,22 @@ range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_CAP);
     EnableWindow(cur_ctrl, !filtered_active);
     if (range->remove_ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.count - range->ignored_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.count - range->ignored_cnt);
     } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.count);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.count);
     }
     SetWindowText(cur_ctrl, static_val);
 
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_DISP);
     EnableWindow(cur_ctrl, filtered_active);
+    if (range->include_dependents)
+      displayed_cnt = range->displayed_plus_dependents_cnt;
+    else
+      displayed_cnt = range->displayed_cnt;
     if (range->remove_ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_cnt - range->displayed_ignored_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_cnt - range->displayed_ignored_cnt);
     } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_cnt);
     }
     SetWindowText(cur_ctrl, static_val);
 
@@ -1710,18 +1853,18 @@ range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_CAP);
     EnableWindow(cur_ctrl, selected_num && !filtered_active);
     if (range->remove_ignored && cfile.current_frame && cfile.current_frame->flags.ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("0"));
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("0"));
     } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), selected_num ? 1 : 0);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), selected_num ? 1 : 0);
     }
     SetWindowText(cur_ctrl, static_val);
 
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_DISP);
     EnableWindow(cur_ctrl, selected_num && filtered_active);
     if (range->remove_ignored && cfile.current_frame && cfile.current_frame->flags.ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("0"));
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("0"));
     } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), selected_num ? 1 : 0);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), selected_num ? 1 : 0);
     }
     SetWindowText(cur_ctrl, static_val);
 
@@ -1732,18 +1875,18 @@ range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_CAP);
     EnableWindow(cur_ctrl, cfile.marked_count && !filtered_active);
     if (range->remove_ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.marked_count - range->ignored_marked_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.marked_count - range->ignored_marked_cnt);
     } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.marked_count);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), cfile.marked_count);
     }
     SetWindowText(cur_ctrl, static_val);
 
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_DISP);
     EnableWindow(cur_ctrl, cfile.marked_count && filtered_active);
     if (range->remove_ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt - range->displayed_ignored_marked_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt - range->displayed_ignored_marked_cnt);
     } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt);
     }
     SetWindowText(cur_ctrl, static_val);
 
@@ -1754,39 +1897,67 @@ range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_CAP);
     EnableWindow(cur_ctrl, range->mark_range_cnt && !filtered_active);
     if (range->remove_ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->mark_range_cnt - range->ignored_mark_range_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->mark_range_cnt - range->ignored_mark_range_cnt);
     } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->mark_range_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->mark_range_cnt);
     }
     SetWindowText(cur_ctrl, static_val);
 
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_DISP);
     EnableWindow(cur_ctrl, range->displayed_mark_range_cnt && filtered_active);
     if (range->remove_ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt - range->displayed_ignored_mark_range_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt - range->displayed_ignored_mark_range_cnt);
     } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt);
+        StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt);
     }
     SetWindowText(cur_ctrl, static_val);
 
     /* RANGE_SELECT_USER */
-    cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
-    EnableWindow(cur_ctrl, !filtered_active);
-    if (range->remove_ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->user_range_cnt - range->ignored_user_range_cnt);
-    } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->user_range_cnt);
-    }
-    SetWindowText(cur_ctrl, static_val);
+    switch (packet_range_check(range)) {
+        case CVT_NO_ERROR:
+            cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
+            SendMessage(cur_ctrl, EM_SETBKGNDCOLOR, (WPARAM) 1, COLOR_WINDOW);
+
+            cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
+            EnableWindow(cur_ctrl, !filtered_active);
+            if (range->remove_ignored) {
+                StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->user_range_cnt - range->ignored_user_range_cnt);
+            } else {
+                StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->user_range_cnt);
+            }
+            SetWindowText(cur_ctrl, static_val);
 
-    cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
-    EnableWindow(cur_ctrl, filtered_active);
-    if (range->remove_ignored) {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_user_range_cnt - range->displayed_ignored_user_range_cnt);
-    } else {
-        _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_user_range_cnt);
+            cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
+            EnableWindow(cur_ctrl, filtered_active);
+            if (range->remove_ignored) {
+                StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_user_range_cnt - range->displayed_ignored_user_range_cnt);
+            } else {
+                StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_user_range_cnt);
+            }
+            SetWindowText(cur_ctrl, static_val);
+            break;
+        case CVT_SYNTAX_ERROR:
+            if (range->process == range_process_user_range) range_valid = FALSE;
+            cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
+            SendMessage(cur_ctrl, EM_SETBKGNDCOLOR, 0, RGB(0xff, 0xcc, 0xcc));
+            cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
+            SetWindowText(cur_ctrl, _T("Bad range"));
+            cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
+            SetWindowText(cur_ctrl, _T("-"));
+            break;
+        case CVT_NUMBER_TOO_BIG:
+            if (range->process == range_process_user_range) range_valid = FALSE;
+            cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
+            SendMessage(cur_ctrl, EM_SETBKGNDCOLOR, 0, RGB(0xff, 0xcc, 0xcc));
+            cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
+            SetWindowText(cur_ctrl, _T("Too large"));
+            cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
+            SetWindowText(cur_ctrl, _T("-"));
+           break;
+
+        default:
+            g_assert_not_reached();
     }
-    SetWindowText(cur_ctrl, static_val);
 
     /* RANGE_REMOVE_IGNORED_PACKETS */
     switch(range->process) {
@@ -1819,13 +1990,16 @@ range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
 
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_IGNORED_CAP);
     EnableWindow(cur_ctrl, ignored_cnt && !filtered_active);
-    _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), ignored_cnt);
+    StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), ignored_cnt);
     SetWindowText(cur_ctrl, static_val);
 
     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_IGNORED_DISP);
     EnableWindow(cur_ctrl, displayed_ignored_cnt && filtered_active);
-    _snwprintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_ignored_cnt);
+    StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_ignored_cnt);
     SetWindowText(cur_ctrl, static_val);
+
+    cur_ctrl = GetDlgItem(GetParent(dlg_hwnd), IDOK);
+    EnableWindow(cur_ctrl, range_valid);
 }
 
 static void
@@ -1839,6 +2013,12 @@ range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range) {
         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
     SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
 
+    /* Retain the filter text, and fill it in. */
+    if(range->user_range != NULL) {
+        cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
+        SetWindowText(cur_ctrl, utf_8to16(range_convert_range(range->user_range)));
+    }
+
     /* dynamic values in the range frame */
     range_update_dynamics(dlg_hwnd, range);
 
@@ -1870,6 +2050,8 @@ range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t
     HWND  cur_ctrl;
     TCHAR range_text[RANGE_TEXT_MAX];
 
+    if (!range) return;
+
     switch(w_param) {
         case (BN_CLICKED << 16) | EWFD_CAPTURED_BTN:
         case (BN_CLICKED << 16) | EWFD_DISPLAYED_BTN:
@@ -1916,7 +2098,7 @@ range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t
             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
             SendMessage(cur_ctrl, BM_CLICK, 0, 0);
             break;
-        case (EN_CHANGE << 16) | EWFD_RANGE_EDIT:
+        case (EN_UPDATE << 16) | EWFD_RANGE_EDIT:
             SendMessage(ctrl, WM_GETTEXT, (WPARAM) RANGE_TEXT_MAX, (LPARAM) range_text);
             packet_range_convert_str(range, utf_16to8(range_text));
             range_update_dynamics(dlg_hwnd, range);
@@ -1932,11 +2114,7 @@ range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t
     }
 }
 
-#if (_MSC_VER <= 1200)
-static UINT CALLBACK
-#else
 static UINT_PTR CALLBACK
-#endif
 merge_file_hook_proc(HWND mf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     HWND      cur_ctrl, parent;
     OFNOTIFY *notify = (OFNOTIFY *) l_param;
@@ -1945,34 +2123,34 @@ merge_file_hook_proc(HWND mf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     switch(msg) {
         case WM_INITDIALOG:
             /* Retain the filter text, and fill it in. */
-            if(dfilter_str != NULL) {
+            if(g_dfilter_str != NULL) {
                 cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
-                SetWindowText(cur_ctrl, utf_8to16(dfilter_str));
+                SetWindowText(cur_ctrl, utf_8to16(g_dfilter_str));
             }
 
-            /* Append by default */
-            cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_PREPEND_BTN);
+            /* Chrono by default */
+            cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_CHRONO_BTN);
             SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
-            merge_action = merge_append;
+            g_merge_action = merge_append;
 
-            preview_set_filename(mf_hwnd, NULL);
+            preview_set_file_info(mf_hwnd, NULL);
             break;
         case WM_NOTIFY:
             switch (notify->hdr.code) {
                 case CDN_FILEOK:
                     /* Fetch the read filter */
                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
-                    if (dfilter_str)
-                        g_free(dfilter_str);
-                    dfilter_str = filter_tb_get(cur_ctrl);
+                    if (g_dfilter_str)
+                        g_free(g_dfilter_str);
+                    g_dfilter_str = filter_tb_get(cur_ctrl);
 
                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_CHRONO_BTN);
                     if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
-                        merge_action = merge_chrono;
+                        g_merge_action = merge_chrono;
                     } else {
                         cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_PREPEND_BTN);
                         if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
-                            merge_action = merge_prepend;
+                            g_merge_action = merge_prepend;
                         }
                     }
 
@@ -1981,11 +2159,11 @@ merge_file_hook_proc(HWND mf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
                     /* This _almost_ works correctly.  We need to handle directory
                        selections, etc. */
                     parent = GetParent(mf_hwnd);
-                    CommDlg_OpenSave_GetSpec(parent, sel_name, MAX_PATH);
-                    preview_set_filename(mf_hwnd, utf_16to8(sel_name));
+                    CommDlg_OpenSave_GetFilePath(parent, sel_name, MAX_PATH);
+                    preview_set_file_info(mf_hwnd, utf_16to8(sel_name));
                     break;
                 case CDN_HELP:
-                    topic_cb(NULL, HELP_MERGE_WIN32_DIALOG);
+                    topic_action(HELP_MERGE_WIN32_DIALOG);
                     break;
                 default:
                     break;
@@ -2008,11 +2186,7 @@ merge_file_hook_proc(HWND mf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
 }
 
 
-#if (_MSC_VER <= 1200)
-static UINT CALLBACK
-#else
 static UINT_PTR CALLBACK
-#endif
 export_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     HWND           cur_ctrl;
     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
@@ -2022,7 +2196,7 @@ export_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     switch(msg) {
         case WM_INITDIALOG:
             /* init the printing range */
-            packet_range_init(&print_args.range);
+            packet_range_init(&print_args.range, &cfile);
             /* default to displayed packets */
             print_args.range.process_filtered = TRUE;
             range_handle_wm_initdialog(ef_hwnd, &print_args.range);
@@ -2060,7 +2234,7 @@ export_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
                     }
                     break;
                 case CDN_HELP:
-                    topic_cb(NULL, HELP_EXPORT_FILE_WIN32_DIALOG);
+                    topic_action(HELP_EXPORT_FILE_WIN32_DIALOG);
                     break;
                 default:
                     break;
@@ -2072,11 +2246,7 @@ export_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     return 0;
 }
 
-#if (_MSC_VER <= 1200)
-static UINT CALLBACK
-#else
 static UINT_PTR CALLBACK
-#endif
 export_raw_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     HWND          cur_ctrl;
     OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
@@ -2085,7 +2255,7 @@ export_raw_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param
 
     switch(msg) {
         case WM_INITDIALOG:
-            _snwprintf(raw_msg, STATIC_LABEL_CHARS, _T("%d byte%s of raw binary data will be written"),
+            StringCchPrintf(raw_msg, STATIC_LABEL_CHARS, _T("%d byte%s of raw binary data will be written"),
                     ofnp->lCustData, utf_8to16(plurality(ofnp->lCustData, "", "s")));
             cur_ctrl = GetDlgItem(ef_hwnd, EWFD_EXPORTRAW_ST);
             SetWindowText(cur_ctrl, raw_msg);
@@ -2093,7 +2263,7 @@ export_raw_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param
         case WM_NOTIFY:
             switch (notify->hdr.code) {
                 case CDN_HELP:
-                    topic_cb(NULL, HELP_EXPORT_BYTES_WIN32_DIALOG);
+                    topic_action(HELP_EXPORT_BYTES_WIN32_DIALOG);
                     break;
                 default:
                     break;
@@ -2104,11 +2274,7 @@ export_raw_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param
     return 0;
 }
 
-#if (_MSC_VER <= 1200)
-static UINT CALLBACK
-#else
 static UINT_PTR CALLBACK
-#endif
 export_sslkeys_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
     HWND          cur_ctrl;
     OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
@@ -2117,7 +2283,7 @@ export_sslkeys_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_p
 
     switch(msg) {
         case WM_INITDIALOG:
-            _snwprintf(sslkeys_msg, STATIC_LABEL_CHARS, _T("%d SSL Session Key%s will be written"),
+            StringCchPrintf(sslkeys_msg, STATIC_LABEL_CHARS, _T("%d SSL Session Key%s will be written"),
                     ofnp->lCustData, utf_8to16(plurality(ofnp->lCustData, "", "s")));
             cur_ctrl = GetDlgItem(ef_hwnd, EWFD_EXPORTSSLKEYS_ST);
             SetWindowText(cur_ctrl, sslkeys_msg);
@@ -2125,7 +2291,7 @@ export_sslkeys_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_p
         case WM_NOTIFY:
             switch (notify->hdr.code) {
                 case CDN_HELP:
-                    topic_cb(NULL, HELP_EXPORT_BYTES_WIN32_DIALOG);
+                    topic_action(HELP_EXPORT_BYTES_WIN32_DIALOG);
                     break;
                 default:
                     break;