wireshark/ui/win32/file_dlg_win32.c

2057 lines
76 KiB
C

/* file_dlg_win32.c
* Native Windows file dialog routines
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 2004 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <tchar.h>
#include <stdlib.h>
#include <fcntl.h>
#include <windows.h>
#include <commdlg.h>
#include <richedit.h>
#include <strsafe.h>
#include "globals.h"
#include "wsutil/file_util.h"
#include "wsutil/str_util.h"
#include "wsutil/unicode-utils.h"
#include "wsutil/filesystem.h"
#include "epan/prefs.h"
#include "ui/alert_box.h"
#include "ui/help_url.h"
#include "ui/last_open_dir.h"
#include "ui/simple_dialog.h"
#include "ui/util.h"
#include "ui/ws_ui_util.h"
#include "ui/all_files_wildcard.h"
#include "file_dlg_win32.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_TYPES_EXPORT \
_T("Plain text (*.txt)\0") _T("*.txt\0") \
_T("PostScript (*.ps)\0") _T("*.ps\0") \
_T("CSV (Comma Separated Values summary) (*.csv)\0") _T("*.csv\0") \
_T("PSML (XML packet summary) (*.psml)\0") _T("*.psml\0") \
_T("PDML (XML packet detail) (*.pdml)\0") _T("*.pdml\0") \
_T("C Arrays (packet bytes) (*.c)\0") _T("*.c\0") \
_T("JSON (*.json)\0") _T("*.json\0")
static TCHAR *FILE_EXT_EXPORT[] =
{
_T(""), /* export type starts at 1 */
_T("txt"),
_T("ps"),
_T("csv"),
_T("psml"),
_T("pdml"),
_T("c"),
_T("json")
};
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 save_as_statstree_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 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_open_type_list(void);
static TCHAR *build_file_save_type_list(GArray *savable_file_types);
#ifdef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
typedef DPI_AWARENESS_CONTEXT (WINAPI *GetThreadDpiAwarenessContextProc)(void);
typedef DPI_AWARENESS_CONTEXT (WINAPI *SetThreadDpiAwarenessContextProc)(DPI_AWARENESS_CONTEXT);
static GetThreadDpiAwarenessContextProc GetThreadDpiAwarenessContextP;
static SetThreadDpiAwarenessContextProc SetThreadDpiAwarenessContextP;
static gboolean got_proc_addresses = FALSE;
static gboolean get_proc_addresses(void) {
if (got_proc_addresses) return TRUE;
HMODULE u32_module = LoadLibrary(_T("User32.dll"));
if (!u32_module) {
got_proc_addresses = FALSE;
return FALSE;
}
gboolean got_all = TRUE;
GetThreadDpiAwarenessContextP = (GetThreadDpiAwarenessContextProc) GetProcAddress(u32_module, "GetThreadDpiAwarenessContext");
if (!GetThreadDpiAwarenessContextP) got_all = FALSE;
SetThreadDpiAwarenessContextP = (SetThreadDpiAwarenessContextProc) GetProcAddress(u32_module, "SetThreadDpiAwarenessContext");
if (!SetThreadDpiAwarenessContextP) got_all = FALSE;
got_proc_addresses = got_all;
return got_all;
}
// Enabling DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 causes issues
// when dragging our open file dialog between differently-DPIed
// displays. It might be time to break down and switch to common
// item dialogs.
HANDLE set_thread_per_monitor_v2_awareness(void) {
if (! get_proc_addresses()) return 0;
#if 0
WCHAR info[100];
StringCchPrintf(info, 100,
L"GetThrDpiAwarenessCtx: %d",
GetThreadDpiAwarenessContextP());
MessageBox(NULL, info, _T("DPI info"), MB_OK);
#endif
return (HANDLE) SetThreadDpiAwarenessContextP(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
void revert_thread_per_monitor_v2_awareness(HANDLE context) {
if (! get_proc_addresses()) return;
SetThreadDpiAwarenessContextP((DPI_AWARENESS_CONTEXT) context);
}
#else // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
HANDLE set_thread_per_monitor_v2_awareness(void) { return 0; }
void revert_thread_per_monitor_v2_awareness(HANDLE context _U_) { }
#endif // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
static int g_filetype;
static gboolean g_compressed;
static packet_range_t *g_range;
static capture_file *g_cf;
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
* print dialog and put range widgets in it as well,
* it might be moved to a separate file.
*
* However, the save file dialog hogs the foreground, so
* this may not be necessary (and, in fact, the file dialogs
* should arguably be modal to the window for the file
* being opened/saved/etc.).
*/
static HWND g_sf_hwnd = NULL;
static char *g_dfilter_str = NULL;
static unsigned int g_format_type = WTAP_TYPE_AUTO;
/*
* According to https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb776913(v=vs.85)
* we should use IFileOpenDialog and IFileSaveDialog on Windows Vista
* and later.
*/
gboolean
win32_open_file (HWND h_wnd, GString *file_name, unsigned int *type, GString *display_filter) {
OPENFILENAME *ofn;
TCHAR file_name16[MAX_PATH] = _T("");
int ofnsize = sizeof(OPENFILENAME);
BOOL gofn_ok;
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;
}
ofn = g_malloc0(ofnsize);
ofn->lStructSize = ofnsize;
ofn->hwndOwner = h_wnd;
ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
ofn->lpstrFilter = build_file_open_type_list();
ofn->lpstrCustomFilter = NULL;
ofn->nMaxCustFilter = 0;
ofn->nFilterIndex = FILE_OPEN_DEFAULT;
ofn->lpstrFile = file_name16;
ofn->nMaxFile = MAX_PATH;
ofn->lpstrFileTitle = NULL;
ofn->nMaxFileTitle = 0;
if (prefs.gui_fileopen_style == FO_STYLE_SPECIFIED && prefs.gui_fileopen_dir[0] != '\0') {
ofn->lpstrInitialDir = utf_8to16(prefs.gui_fileopen_dir);
} else {
ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
}
ofn->lpstrTitle = _T("Wireshark: Open Capture File");
ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER |
OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
OFN_ENABLEHOOK | OFN_SHOWHELP;
ofn->lpstrDefExt = NULL;
ofn->lpfnHook = open_file_hook_proc;
ofn->lpTemplateName = _T("WIRESHARK_OPENFILENAME_TEMPLATE");
HANDLE save_da_ctx = set_thread_per_monitor_v2_awareness();
gofn_ok = GetOpenFileName(ofn);
revert_thread_per_monitor_v2_awareness(save_da_ctx);
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 : "");
*type = g_format_type;
}
g_free( (void *) ofn->lpstrFilter);
g_free( (void *) ofn);
g_free(g_dfilter_str);
g_dfilter_str = NULL;
return gofn_ok;
}
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(file_type, 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 - given that we no longer support releases prior to
Windows Vista, we should use a task dialog:
https://docs.microsoft.com/en-us/windows/win32/controls/bumper-task-dialog-task-dialogs-reference
created with TaskDialogIndirect():
https://docs.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-taskdialogindirect
because the TASKDIALOGCONFIG structure
https://docs.microsoft.com/en-us/windows/win32/api/commctrl/ns-commctrl-taskdialogconfig
supports adding custom buttons, with custom labels, unlike
a MessageBox(), which doesn't appear to offer a clean way to
do that. */
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 {
/* 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);
}
switch (response) {
case IDNO: /* "No" means "Save in another format" in the first dialog */
/* OK, the only other format we support is pcapng. 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 pcapng 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;
}
}
gboolean
win32_save_as_file(HWND h_wnd, capture_file *cf, GString *file_name, int *file_type,
wtap_compression_type *compression_type,
gboolean must_support_all_comments)
{
guint32 required_comment_types;
GArray *savable_file_types;
OPENFILENAME *ofn;
TCHAR file_name16[MAX_PATH] = _T("");
int ofnsize = sizeof(OPENFILENAME);
BOOL gsfn_ok;
if (!file_name || !file_type || !compression_type)
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_subtypes(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;
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: Save file as");
ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER |
OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
OFN_PATHMUSTEXIST | OFN_ENABLEHOOK | OFN_SHOWHELP;
ofn->lpstrDefExt = NULL;
ofn->lCustData = (LPARAM) cf;
ofn->lpfnHook = save_as_file_hook_proc;
ofn->lpTemplateName = _T("WIRESHARK_SAVEASFILENAME_TEMPLATE");
HANDLE save_da_ctx = set_thread_per_monitor_v2_awareness();
gsfn_ok = GetSaveFileName(ofn);
revert_thread_per_monitor_v2_awareness(save_da_ctx);
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);
*compression_type = g_compressed ? WTAP_GZIP_COMPRESSED : WTAP_UNCOMPRESSED;
} 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_array_free(savable_file_types, TRUE);
g_free( (void *) ofn->lpstrFilter);
g_free( (void *) ofn);
return gsfn_ok;
}
gboolean win32_save_as_statstree(HWND h_wnd, GString *file_name, int *file_type)
{
OPENFILENAME *ofn;
TCHAR file_name16[MAX_PATH] = _T("");
int ofnsize = sizeof(OPENFILENAME);
BOOL gsfn_ok;
if (!file_name || !file_type)
return FALSE;
if (file_name->len > 0) {
StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
}
ofn = g_malloc0(sizeof(OPENFILENAME));
ofn->lStructSize = ofnsize;
ofn->hwndOwner = h_wnd;
ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
ofn->lpstrFilter = _T("Plain text file (.txt)\0*.txt\0Comma separated values (.csv)\0*.csv\0XML document (.xml)\0*.xml\0YAML document (.yaml)\0*.yaml\0");
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: Save stats tree as ...");
ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER |
OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
ofn->lpstrDefExt = NULL;
ofn->lpfnHook = save_as_statstree_hook_proc;
ofn->lpTemplateName = _T("WIRESHARK_SAVEASSTATSTREENAME_TEMPLATE");
HANDLE save_da_ctx = set_thread_per_monitor_v2_awareness();
gsfn_ok = GetSaveFileName(ofn);
revert_thread_per_monitor_v2_awareness(save_da_ctx);
if (gsfn_ok) {
g_string_printf(file_name, "%s", utf_16to8(file_name16));
/* What file format was specified? */
*file_type = ofn->nFilterIndex - 1;
}
g_sf_hwnd = NULL;
g_free( (void *) ofn);
return gsfn_ok;
}
gboolean
win32_export_specified_packets_file(HWND h_wnd, capture_file *cf,
GString *file_name,
int *file_type,
wtap_compression_type *compression_type,
packet_range_t *range) {
GArray *savable_file_types;
OPENFILENAME *ofn;
TCHAR file_name16[MAX_PATH] = _T("");
int ofnsize = sizeof(OPENFILENAME);
BOOL gsfn_ok;
if (!file_name || !file_type || !compression_type || !range)
return FALSE;
if (file_name->len > 0) {
StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
}
savable_file_types = wtap_get_savable_file_types_subtypes(cf->cd_t,
cf->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_cf = cf;
g_compressed = FALSE;
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->lCustData = (LPARAM) cf;
ofn->lpfnHook = export_specified_packets_file_hook_proc;
ofn->lpTemplateName = _T("WIRESHARK_EXPORT_SPECIFIED_PACKETS_FILENAME_TEMPLATE");
HANDLE save_da_ctx = set_thread_per_monitor_v2_awareness();
gsfn_ok = GetSaveFileName(ofn);
revert_thread_per_monitor_v2_awareness(save_da_ctx);
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);
*compression_type = g_compressed ? WTAP_GZIP_COMPRESSED : WTAP_UNCOMPRESSED;
} 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_cf = NULL;
g_array_free(savable_file_types, TRUE);
g_free( (void *) ofn->lpstrFilter);
g_free( (void *) ofn);
return gsfn_ok;
}
gboolean
win32_merge_file (HWND h_wnd, GString *file_name, GString *display_filter, int *merge_type) {
OPENFILENAME *ofn;
TCHAR file_name16[MAX_PATH] = _T("");
int ofnsize = sizeof(OPENFILENAME);
BOOL gofn_ok;
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;
}
ofn = g_malloc0(ofnsize);
ofn->lStructSize = ofnsize;
ofn->hwndOwner = h_wnd;
ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
ofn->lpstrFilter = build_file_open_type_list();
ofn->lpstrCustomFilter = NULL;
ofn->nMaxCustFilter = 0;
ofn->nFilterIndex = FILE_MERGE_DEFAULT;
ofn->lpstrFile = file_name16;
ofn->nMaxFile = MAX_PATH;
ofn->lpstrFileTitle = NULL;
ofn->nMaxFileTitle = 0;
if (prefs.gui_fileopen_style == FO_STYLE_SPECIFIED && prefs.gui_fileopen_dir[0] != '\0') {
ofn->lpstrInitialDir = utf_8to16(prefs.gui_fileopen_dir);
} else {
ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
}
ofn->lpstrTitle = _T("Wireshark: Merge with capture file");
ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER |
OFN_NOCHANGEDIR | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY |
OFN_ENABLEHOOK | OFN_SHOWHELP;
ofn->lpstrDefExt = NULL;
ofn->lpfnHook = merge_file_hook_proc;
ofn->lpTemplateName = _T("WIRESHARK_MERGEFILENAME_TEMPLATE");
HANDLE save_da_ctx = set_thread_per_monitor_v2_awareness();
gofn_ok = GetOpenFileName(ofn);
revert_thread_per_monitor_v2_awareness(save_da_ctx);
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 : "");
switch (g_merge_action) {
case merge_append:
*merge_type = 1;
break;
case merge_chrono:
*merge_type = 0;
break;
case merge_prepend:
*merge_type = -1;
break;
default:
g_assert_not_reached();
}
}
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, capture_file *cf, export_type_e export_type) {
OPENFILENAME *ofn;
TCHAR file_name[MAX_PATH] = _T("");
char *dirname;
cf_print_status_t status;
int ofnsize = sizeof(OPENFILENAME);
g_cf = cf;
ofn = g_malloc0(ofnsize);
ofn->lStructSize = ofnsize;
ofn->hwndOwner = h_wnd;
ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
ofn->lpstrFilter = FILE_TYPES_EXPORT;
ofn->lpstrCustomFilter = NULL;
ofn->nMaxCustFilter = 0;
ofn->nFilterIndex = export_type;
ofn->lpstrFile = file_name;
ofn->nMaxFile = MAX_PATH;
ofn->lpstrFileTitle = NULL;
ofn->nMaxFileTitle = 0;
ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
ofn->lpstrTitle = _T("Wireshark: Export File");
ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER |
OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
OFN_PATHMUSTEXIST | OFN_ENABLEHOOK | OFN_SHOWHELP;
ofn->lpstrDefExt = FILE_EXT_EXPORT[export_type];
ofn->lCustData = (LPARAM) cf;
ofn->lpfnHook = export_file_hook_proc;
ofn->lpTemplateName = _T("WIRESHARK_EXPORTFILENAME_TEMPLATE");
/* Fill in our print (and export) args */
print_args.format = PR_FMT_TEXT;
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;
print_args.stream = NULL;
HANDLE save_da_ctx = set_thread_per_monitor_v2_awareness();
BOOL gsfn_ok = GetSaveFileName(ofn);
revert_thread_per_monitor_v2_awareness(save_da_ctx);
if (gsfn_ok) {
print_args.file = utf_16to8(file_name);
switch (ofn->nFilterIndex) {
case export_type_text: /* Text */
print_args.stream = print_stream_text_new(TRUE, print_args.file);
if (print_args.stream == NULL) {
open_failure_alert_box(print_args.file, errno, TRUE);
g_free( (void *) ofn);
return;
}
status = cf_print_packets(cf, &print_args, TRUE);
break;
case export_type_ps: /* PostScript (r) */
print_args.stream = print_stream_ps_new(TRUE, print_args.file);
if (print_args.stream == NULL) {
open_failure_alert_box(print_args.file, errno, TRUE);
g_free( (void *) ofn);
return;
}
status = cf_print_packets(cf, &print_args, TRUE);
break;
case export_type_csv: /* CSV */
status = cf_write_csv_packets(cf, &print_args);
break;
case export_type_carrays: /* C Arrays */
status = cf_write_carrays_packets(cf, &print_args);
break;
case export_type_psml: /* PSML */
status = cf_write_psml_packets(cf, &print_args);
break;
case export_type_pdml: /* PDML */
status = cf_write_pdml_packets(cf, &print_args);
break;
case export_type_json: /* JSON */
status = cf_write_json_packets(cf, &print_args);
break;
default:
g_free( (void *) ofn);
return;
}
switch (status) {
case CF_PRINT_OK:
break;
case CF_PRINT_OPEN_ERROR:
open_failure_alert_box(print_args.file, errno, TRUE);
break;
case CF_PRINT_WRITE_ERROR:
write_failure_alert_box(print_args.file, errno);
break;
}
/* Save the directory name for future file dialogs. */
dirname = get_dirname(utf_16to8(file_name)); /* Overwrites cf_name */
set_last_open_dir(dirname);
}
g_cf = NULL;
g_free( (void *) ofn);
}
/*
* Private routines
*/
/** Given a print_args_t struct, update a set of print/export format controls
* accordingly.
*
* @param dlg_hwnd HWND of the dialog in question.
* @param args Pointer to a print args struct.
*/
static void
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) {
args->print_summary = TRUE;
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) {
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
switch (SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0)) {
case 0:
args->print_dissections = print_dissections_collapsed;
break;
case 1:
args->print_dissections = print_dissections_as_displayed;
break;
case 2:
args->print_dissections = print_dissections_expanded;
break;
default:
g_assert_not_reached();
}
EnableWindow(cur_ctrl, TRUE);
} else {
args->print_dissections = print_dissections_none;
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
EnableWindow(cur_ctrl, FALSE);
}
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_BYTES_CB);
if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
args->print_hex = TRUE;
else
args->print_hex = FALSE;
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_NEW_PAGE_CB);
if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
args->print_formfeed = TRUE;
else
args->print_formfeed = FALSE;
}
static void
format_handle_wm_initdialog(HWND dlg_hwnd, print_args_t *args) {
HWND cur_ctrl;
/* 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);
SendMessage(cur_ctrl, BM_SETCHECK, args->print_dissections != print_dissections_none, 0);
/* Set the "Packet details" combo */
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("All collapsed"));
SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("As displayed"));
SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("All expanded"));
switch (args->print_dissections) {
case print_dissections_none:
case print_dissections_collapsed:
SendMessage(cur_ctrl, CB_SETCURSEL, 0, 0);
break;
case print_dissections_as_displayed:
SendMessage(cur_ctrl, CB_SETCURSEL, 1, 0);
break;
case print_dissections_expanded:
SendMessage(cur_ctrl, CB_SETCURSEL, 2, 0);
default:
g_assert_not_reached();
}
/* Set the "Packet bytes" box */
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_BYTES_CB);
SendMessage(cur_ctrl, BM_SETCHECK, args->print_hex, 0);
/* Set the "Each packet on a new page" box */
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_NEW_PAGE_CB);
SendMessage(cur_ctrl, BM_SETCHECK, args->print_formfeed, 0);
print_update_dynamic(dlg_hwnd, args);
}
#define PREVIEW_STR_MAX 200
/* If preview_file is NULL, disable the elements. If not, enable and
* show the preview info. */
static gboolean
preview_set_file_info(HWND of_hwnd, gchar *preview_file) {
HWND cur_ctrl;
int i;
wtap *wth;
int err;
gchar *err_info;
ws_file_preview_stats stats;
ws_file_preview_stats_status status;
TCHAR string_buff[PREVIEW_STR_MAX];
TCHAR first_buff[PREVIEW_STR_MAX];
gint64 filesize;
gchar *size_str;
time_t ti_time;
struct tm *ti_tm;
guint elapsed_time;
for (i = EWFD_PTX_FORMAT; i <= EWFD_PTX_START_ELAPSED; i++) {
cur_ctrl = GetDlgItem(of_hwnd, i);
if (cur_ctrl) {
EnableWindow(cur_ctrl, FALSE);
}
}
for (i = EWFD_PTX_FORMAT; i <= EWFD_PTX_START_ELAPSED; i++) {
cur_ctrl = GetDlgItem(of_hwnd, i);
if (cur_ctrl) {
SetWindowText(cur_ctrl, _T("-"));
}
}
if (preview_file == NULL || strlen(preview_file) < 1) {
return FALSE;
}
/* Format: directory */
cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
if (test_for_directory(preview_file) == EISDIR) {
SetWindowText(cur_ctrl, _T("directory"));
return FALSE;
}
wth = wtap_open_offline(preview_file, WTAP_TYPE_AUTO, &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;
}
/* Success! */
for (i = EWFD_PT_FORMAT; i <= EWFD_PTX_START_ELAPSED; i++) {
cur_ctrl = GetDlgItem(of_hwnd, i);
if (cur_ctrl) {
EnableWindow(cur_ctrl, TRUE);
}
}
/* Format */
cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
SetWindowText(cur_ctrl, utf_8to16(wtap_file_type_subtype_string(wtap_file_type_subtype(wth))));
/* Size */
filesize = wtap_file_size(wth, &err);
// Windows Explorer uses IEC.
size_str = format_size(filesize, format_size_unit_bytes|format_size_prefix_iec);
status = get_stats_for_preview(wth, &stats, &err, &err_info);
if(status == PREVIEW_READ_ERROR) {
/* XXX - give error details? */
g_free(err_info);
utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%s, error after %u records",
size_str, stats.records);
g_free(size_str);
cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_SIZE);
SetWindowText(cur_ctrl, string_buff);
wtap_close(wth);
return TRUE;
}
/* Packet count */
if(status == PREVIEW_TIMED_OUT) {
utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%s, timed out at %u data records",
size_str, stats.data_records);
} else {
utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%s, %u data records",
size_str, stats.data_records);
}
g_free(size_str);
cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_SIZE);
SetWindowText(cur_ctrl, string_buff);
/* First packet / elapsed time */
if(stats.have_times) {
/*
* We saw at least one record with a time stamp, so we can give
* a start time (if we have a mix of records with and without
* time stamps, and there were records without time stamps
* before the one with a time stamp, this may be inaccurate).
*/
ti_time = (long)stats.start_time;
ti_tm = localtime( &ti_time );
if(ti_tm) {
StringCchPrintf(first_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(first_buff, PREVIEW_STR_MAX, _T("?"));
}
} else {
StringCchPrintf(first_buff, PREVIEW_STR_MAX, _T("unknown"));
}
/* Elapsed time */
if(status == PREVIEW_SUCCEEDED && stats.have_times) {
/*
* We didn't time out, so we looked at all packets, and we got
* at least one packet with a time stamp, so we can calculate
* an elapsed time from the time stamp of the last packet with
* with a time stamp (if we have a mix of records with and without
* time stamps, and there were records without time stamps after
* the last one with a time stamp, this may be inaccurate).
*/
elapsed_time = (unsigned int)(stats.stop_time-stats.start_time);
if(status == PREVIEW_TIMED_OUT) {
StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%s / unknown"), first_buff);
} else if(elapsed_time/86400) {
StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%s / %02u days %02u:%02u:%02u"),
first_buff, elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
} else {
StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%s / %02u:%02u:%02u"),
first_buff, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
}
} else {
StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%s / unknown"),
first_buff);
}
cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_START_ELAPSED);
SetWindowText(cur_ctrl, string_buff);
wtap_close(wth);
return TRUE;
}
static char *
filter_tb_get(HWND hwnd) {
TCHAR *strval = NULL;
gint len;
char *ret;
/* If filter_text is non-NULL, use it. Otherwise, grab the text from
* the window */
len = GetWindowTextLength(hwnd);
if (len > 0) {
len++;
strval = g_malloc(len*sizeof(TCHAR));
len = GetWindowText(hwnd, strval, len);
ret = g_utf16_to_utf8(strval, -1, NULL, NULL, NULL);
g_free(strval);
return ret;
} else {
return NULL;
}
}
/* XXX - Copied from "filter-util.c" in the wireshark-win32 branch */
/* XXX - The only reason for the "filter_text" parameter is to be able to feed
* in the "real" filter string in the case of a CBN_SELCHANGE notification message.
*/
static void
filter_tb_syntax_check(HWND hwnd, TCHAR *filter_text) {
TCHAR *strval = NULL;
gint len;
dfilter_t *dfp;
/* If filter_text is non-NULL, use it. Otherwise, grab the text from
* the window */
if (filter_text) {
len = (lstrlen(filter_text) + 1) * sizeof(TCHAR);
strval = g_malloc(len);
memcpy(strval, filter_text, len);
} else {
len = GetWindowTextLength(hwnd);
if (len > 0) {
len++;
strval = g_malloc(len*sizeof(TCHAR));
len = GetWindowText(hwnd, strval, len);
}
}
if (len == 0) {
/* Default window background */
SendMessage(hwnd, EM_SETBKGNDCOLOR, (WPARAM) 1, COLOR_WINDOW);
return;
} else if (dfilter_compile(utf_16to8(strval), &dfp, NULL)) { /* colorize filter string entry */
dfilter_free(dfp);
/* Valid (light green) */
SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, RGB(0xe4, 0xff, 0xc7)); /* tango_chameleon_1 */
} else {
/* Invalid (light red) */
SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, RGB(0xff, 0xcc, 0xcc)); /* tango_scarlet_red_1 */
}
g_free(strval);
}
static UINT_PTR CALLBACK
open_file_hook_proc(HWND of_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
HWND cur_ctrl, parent;
OFNOTIFY *notify = (OFNOTIFY *) l_param;
TCHAR sel_name[MAX_PATH];
gint i;
switch(msg) {
case WM_INITDIALOG:
/* Retain the filter text, and fill it in. */
if(g_dfilter_str != NULL) {
cur_ctrl = GetDlgItem(of_hwnd, EWFD_FILTER_EDIT);
SetWindowText(cur_ctrl, utf_8to16(g_dfilter_str));
}
cur_ctrl = GetDlgItem(of_hwnd, EWFD_FORMAT_TYPE);
SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("Automatically detect file type"));
for (i = 0; open_routines[i].name != NULL; i += 1) {
SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) utf_8to16(open_routines[i].name));
}
SendMessage(cur_ctrl, CB_SETCURSEL, 0, 0);
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);
g_free(g_dfilter_str);
g_dfilter_str = filter_tb_get(cur_ctrl);
cur_ctrl = GetDlgItem(of_hwnd, EWFD_FORMAT_TYPE);
g_format_type = (unsigned int) SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0);
break;
case CDN_SELCHANGE:
/* This _almost_ works correctly. We need to handle directory
selections, etc. */
parent = GetParent(of_hwnd);
CommDlg_OpenSave_GetFilePath(parent, sel_name, MAX_PATH);
preview_set_file_info(of_hwnd, utf_16to8(sel_name));
break;
case CDN_HELP:
topic_action(HELP_OPEN_WIN32_DIALOG);
break;
default:
break;
}
break;
case WM_COMMAND:
cur_ctrl = (HWND) l_param;
switch(w_param) {
case (EN_UPDATE << 16) | EWFD_FILTER_EDIT:
filter_tb_syntax_check(cur_ctrl, NULL);
break;
/*
* If we ever figure out a way to integrate the Windows
* and GTK+ event loops (or make a native filter dialog),
* we can re-enable the "Filter" button.
*/
/*
case EWFD_FILTER_BTN:
break;
*/
default:
break;
}
break;
default:
break;
}
return 0;
}
/* Generate a list of the file types we can filter for in the open dialog. */
static void
append_file_extension_type(GArray *sa, int et)
{
GString* pattern_str = g_string_new("");
GString* description_str = g_string_new("");
gchar sep;
GSList *extensions_list, *extension;
const TCHAR *str16;
guint16 zero = 0;
/* Construct the list of patterns. */
extensions_list = wtap_get_file_extension_type_extensions(et);
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_extensions_list(extensions_list);
/* Construct the description. */
g_string_printf(description_str, "%s (%s)",
wtap_get_file_extension_type_name(et),
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);
g_string_free(description_str, TRUE);
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);
g_string_free(pattern_str, TRUE);
}
static TCHAR *
build_file_open_type_list(void) {
const TCHAR *str16;
int et;
GArray* sa;
static const guint16 zero = 0;
GString* pattern_str;
gchar sep;
GSList *extensions_list, *extension;
/*
* Microsoft's UI guidelines say, of the file filters in open and
* save dialogs:
*
* For meta-filters, remove the file extension list to eliminate
* clutter. Examples: "All files," "All pictures," "All music,"
* and "All videos."
*
* so we omit them (for "All Capture Files", the filter would be
* *really* long). On both Windows XP and Windows 7, Wordpad doesn't
* do that, but Paint does.
*/
/*
* Array of hexadectets used as a sequence of null-terminated
* UTF-16 strings.
*/
sa = g_array_new(FALSE /*zero_terminated*/, FALSE /*clear_*/,2 /*element_size*/);
/* 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(ALL_FILES_WILDCARD);
sa = g_array_append_vals(sa, str16, (guint) strlen(ALL_FILES_WILDCARD));
sa = g_array_append_val(sa, zero);
/*
* Add an "All Capture Files" entry, with all the capture file
* extensions we know about.
*/
str16 = utf_8to16("All Capture Files");
sa = g_array_append_vals(sa, str16, (guint) strlen("All Capture Files"));
sa = g_array_append_val(sa, zero);
/*
* Construct its list of patterns.
*/
pattern_str = g_string_new("");
extensions_list = wtap_get_all_capture_file_extensions_list();
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_extensions_list(extensions_list);
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);
/* Include all the file type extensions Wireshark supports. */
for (et = 0; et < wtap_get_num_file_type_extensions(); et++) {
append_file_extension_type(sa, et);
}
/* terminate the array */
sa = g_array_append_val(sa, zero);
return (TCHAR *) g_array_free(sa, FALSE /*free_segment*/);
}
/* Generate a list of the file types we can save this file as.
"g_filetype" is the type it has now.
"encap" is the encapsulation for its packets (which could be
"unknown" or "per-packet").
"filtered" is TRUE if we're to save only the packets that passed
the display filter (in which case we have to save it using Wiretap)
and FALSE if we're to save the entire file (in which case, if we're
saving it in the type it has already, we can just copy it).
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;
const TCHAR *str16;
guint16 zero = 0;
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 a
wildcard that matches all file names - even those with
no extension, so we don't need to worry about compressed
file extensions. */
g_string_printf(pattern_str, ALL_FILES_WILDCARD);
} 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_extensions_list(extensions_list);
}
/* Construct the description. */
g_string_printf(description_str, "%s (%s)", wtap_file_type_subtype_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);
g_string_free(description_str, TRUE);
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);
g_string_free(pattern_str, TRUE);
}
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;
/* 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);
}
/* terminate the array */
sa = g_array_append_val(sa, zero);
return (TCHAR *) g_array_free(sa, FALSE /*free_segment*/);
}
#if 0
static void
build_file_format_list(HWND sf_hwnd) {
HWND format_cb;
int ft;
guint file_index;
guint item_to_select;
gchar *s;
/* Default to the first supported file type, if the file's current
type isn't supported. */
item_to_select = 0;
format_cb = GetDlgItem(sf_hwnd, EWFD_FILE_TYPE_COMBO);
SendMessage(format_cb, CB_RESETCONTENT, 0, 0);
/* Check all file types. */
file_index = 0;
for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
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 (!wtap_can_save_with_wiretap(ft, cfile.linktypes))
continue; /* We can't. */
}
/* OK, we can write it out in this type. */
if(wtap_file_extensions_string(ft) != NULL) {
s = g_strdup_printf("%s (%s)", wtap_file_type_string(ft), wtap_file_extensions_string(ft));
} else {
s = g_strdup_printf("%s (" ALL_FILES_WILDCARD ")", wtap_file_type_string(ft));
}
SendMessage(format_cb, CB_ADDSTRING, 0, (LPARAM) utf_8to16(s));
g_free(s);
SendMessage(format_cb, CB_SETITEMDATA, (LPARAM) file_index, (WPARAM) ft);
if (ft == g_filetype) {
/* Default to the same format as the file, if it's supported. */
item_to_select = file_index;
}
file_index++;
}
SendMessage(format_cb, CB_SETCURSEL, (WPARAM) item_to_select, 0);
}
#endif
static UINT_PTR CALLBACK
save_as_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, file_index;*/
switch(msg) {
case WM_INITDIALOG: {
OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
capture_file *cf = (capture_file *) ofnp->lCustData;
g_sf_hwnd = sf_hwnd;
/* Default to saving in the file's current format. */
g_filetype = cf->cd_t;
/* 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:
file_index = SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0);
if (file_index != CB_ERR) {
new_filetype = SendMessage(cur_ctrl, CB_GETITEMDATA, (WPARAM) file_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;
OPENFILENAME *ofnp = (OPENFILENAME *) notify->lpOFN;
capture_file *cf = (capture_file *) ofnp->lCustData;
/* 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(cf->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;
}
static UINT_PTR CALLBACK
save_as_statstree_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
switch(msg) {
case WM_INITDIALOG:
g_sf_hwnd = sf_hwnd;
break;
case WM_COMMAND:
break;
case WM_NOTIFY:
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, file_index;*/
switch(msg) {
case WM_INITDIALOG: {
g_sf_hwnd = sf_hwnd;
/* Default to saving all packets, in the file's current format. */
g_filetype = g_cf->cd_t;
/* Fill in the file format list */
/*build_file_format_list(sf_hwnd);*/
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:
cur_ctrl = (HWND) l_param;
switch (w_param) {
#if 0
case (CBN_SELCHANGE << 16) | EWFD_FILE_TYPE_COMBO:
file_index = SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0);
if (file_index != CB_ERR) {
new_filetype = SendMessage(cur_ctrl, CB_GETITEMDATA, (WPARAM) file_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;
}
}
}
break;
#endif
default:
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_action(HELP_SAVE_WIN32_DIALOG);
break;
case CDN_FILEOK: {
HWND parent;
char *file_name8;
OPENFILENAME *ofnp = (OPENFILENAME *) notify->lpOFN;
capture_file *cf = (capture_file *) ofnp->lCustData;
/* 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(cf->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 STATIC_LABEL_CHARS 100
/* For each range static control, fill in its value and enable/disable it. */
static void
range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
HWND cur_ctrl;
gboolean filtered_active = FALSE;
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)
filtered_active = TRUE;
/* RANGE_SELECT_ALL */
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_CAP);
EnableWindow(cur_ctrl, !filtered_active);
if (range->remove_ignored) {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), g_cf->count - range->ignored_cnt);
} else {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), g_cf->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) {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_cnt - range->displayed_ignored_cnt);
} else {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_cnt);
}
SetWindowText(cur_ctrl, static_val);
/* RANGE_SELECT_CURR */
selected_num = (g_cf->current_frame) ? g_cf->current_frame->num : 0;
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_CAP);
EnableWindow(cur_ctrl, selected_num && !filtered_active);
if (range->remove_ignored && g_cf->current_frame && g_cf->current_frame->ignored) {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("0"));
} else {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%d"), 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 && g_cf->current_frame && g_cf->current_frame->ignored) {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("0"));
} else {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%d"), selected_num ? 1 : 0);
}
SetWindowText(cur_ctrl, static_val);
/* RANGE_SELECT_MARKED */
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
EnableWindow(cur_ctrl, g_cf->marked_count);
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_CAP);
EnableWindow(cur_ctrl, g_cf->marked_count && !filtered_active);
if (range->remove_ignored) {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), g_cf->marked_count - range->ignored_marked_cnt);
} else {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), g_cf->marked_count);
}
SetWindowText(cur_ctrl, static_val);
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_DISP);
EnableWindow(cur_ctrl, g_cf->marked_count && filtered_active);
if (range->remove_ignored) {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt - range->displayed_ignored_marked_cnt);
} else {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt);
}
SetWindowText(cur_ctrl, static_val);
/* RANGE_SELECT_MARKED_RANGE */
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
EnableWindow(cur_ctrl, range->mark_range_cnt);
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_CAP);
EnableWindow(cur_ctrl, range->mark_range_cnt && !filtered_active);
if (range->remove_ignored) {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->mark_range_cnt - range->ignored_mark_range_cnt);
} else {
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) {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt - range->displayed_ignored_mark_range_cnt);
} else {
StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt);
}
SetWindowText(cur_ctrl, static_val);
/* RANGE_SELECT_USER */
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) {
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();
}
/* RANGE_REMOVE_IGNORED_PACKETS */
switch(range->process) {
case(range_process_all):
ignored_cnt = range->ignored_cnt;
displayed_ignored_cnt = range->displayed_ignored_cnt;
break;
case(range_process_selected):
ignored_cnt = (g_cf->current_frame && g_cf->current_frame->ignored) ? 1 : 0;
displayed_ignored_cnt = ignored_cnt;
break;
case(range_process_marked):
ignored_cnt = range->ignored_marked_cnt;
displayed_ignored_cnt = range->displayed_ignored_marked_cnt;
break;
case(range_process_marked_range):
ignored_cnt = range->ignored_mark_range_cnt;
displayed_ignored_cnt = range->displayed_ignored_mark_range_cnt;
break;
case(range_process_user_range):
ignored_cnt = range->ignored_user_range_cnt;
displayed_ignored_cnt = range->displayed_ignored_user_range_cnt;
break;
default:
g_assert_not_reached();
}
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_REMOVE_IGN_CB);
EnableWindow(cur_ctrl, ignored_cnt);
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_IGNORED_CAP);
EnableWindow(cur_ctrl, ignored_cnt && !filtered_active);
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);
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
range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range) {
HWND cur_ctrl;
/* Set the appropriate captured/displayed radio */
if (range->process_filtered)
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
else
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) {
char* tmp_str;
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
tmp_str = range_convert_range(NULL, range->user_range);
SetWindowText(cur_ctrl, utf_8to16(tmp_str));
wmem_free(NULL, tmp_str);
}
/* dynamic values in the range frame */
range_update_dynamics(dlg_hwnd, range);
/* Set the appropriate range radio */
switch(range->process) {
case(range_process_all):
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_BTN);
break;
case(range_process_selected):
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_BTN);
break;
case(range_process_marked):
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
break;
case(range_process_marked_range):
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
break;
case(range_process_user_range):
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
break;
default:
g_assert_not_reached();
}
SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
}
static void
range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t *range) {
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:
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
range->process_filtered = FALSE;
else
range->process_filtered = TRUE;
range_update_dynamics(dlg_hwnd, range);
break;
case (BN_CLICKED << 16) | EWFD_ALL_PKTS_BTN:
if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
range->process = range_process_all;
range_update_dynamics(dlg_hwnd, range);
}
break;
case (BN_CLICKED << 16) | EWFD_SEL_PKT_BTN:
if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
range->process = range_process_selected;
range_update_dynamics(dlg_hwnd, range);
}
break;
case (BN_CLICKED << 16) | EWFD_MARKED_BTN:
if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
range->process = range_process_marked;
range_update_dynamics(dlg_hwnd, range);
}
break;
case (BN_CLICKED << 16) | EWFD_FIRST_LAST_BTN:
if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
range->process = range_process_marked_range;
range_update_dynamics(dlg_hwnd, range);
}
break;
case (BN_CLICKED << 16) | EWFD_RANGE_BTN:
if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
range->process = range_process_user_range;
range_update_dynamics(dlg_hwnd, range);
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
SetFocus(cur_ctrl);
}
break;
case (EN_SETFOCUS << 16) | EWFD_RANGE_EDIT:
cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
SendMessage(cur_ctrl, BM_CLICK, 0, 0);
break;
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);
break;
case (BN_CLICKED << 16) | EWFD_REMOVE_IGN_CB:
if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
range->remove_ignored = TRUE;
} else {
range->remove_ignored = FALSE;
}
range_update_dynamics(dlg_hwnd, range);
break;
}
}
static UINT_PTR CALLBACK
merge_file_hook_proc(HWND mf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
HWND cur_ctrl, parent;
OFNOTIFY *notify = (OFNOTIFY *) l_param;
TCHAR sel_name[MAX_PATH];
switch(msg) {
case WM_INITDIALOG:
/* Retain the filter text, and fill it in. */
if(g_dfilter_str != NULL) {
cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
SetWindowText(cur_ctrl, utf_8to16(g_dfilter_str));
}
/* Chrono by default */
cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_CHRONO_BTN);
SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
g_merge_action = merge_append;
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);
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) {
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) {
g_merge_action = merge_prepend;
}
}
break;
case CDN_SELCHANGE:
/* This _almost_ works correctly. We need to handle directory
selections, etc. */
parent = GetParent(mf_hwnd);
CommDlg_OpenSave_GetFilePath(parent, sel_name, MAX_PATH);
preview_set_file_info(mf_hwnd, utf_16to8(sel_name));
break;
case CDN_HELP:
topic_action(HELP_MERGE_WIN32_DIALOG);
break;
default:
break;
}
break;
case WM_COMMAND:
cur_ctrl = (HWND) l_param;
switch(w_param) {
case (EN_UPDATE << 16) | EWFD_FILTER_EDIT:
filter_tb_syntax_check(cur_ctrl, NULL);
break;
default:
break;
}
break;
default:
break;
}
return 0;
}
static UINT_PTR CALLBACK
export_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
HWND cur_ctrl;
OFNOTIFY *notify = (OFNOTIFY *) l_param;
gboolean pkt_fmt_enable;
int i, filter_index;
switch(msg) {
case WM_INITDIALOG: {
OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
capture_file *cf = (capture_file *) ofnp->lCustData;
/* init the printing range */
packet_range_init(&print_args.range, cf);
/* default to displayed packets */
print_args.range.process_filtered = TRUE;
range_handle_wm_initdialog(ef_hwnd, &print_args.range);
format_handle_wm_initdialog(ef_hwnd, &print_args);
break;
}
case WM_COMMAND:
cur_ctrl = (HWND) l_param;
switch (w_param) {
case (CBN_SELCHANGE << 16) | EWFD_PKT_DETAIL_COMBO:
default:
range_handle_wm_command(ef_hwnd, cur_ctrl, w_param, &print_args.range);
print_update_dynamic(ef_hwnd, &print_args);
break;
}
break;
case WM_NOTIFY:
switch (notify->hdr.code) {
case CDN_FILEOK:
break;
case CDN_TYPECHANGE:
filter_index = notify->lpOFN->nFilterIndex;
if (filter_index == 2) /* PostScript */
print_args.format = PR_FMT_TEXT;
else
print_args.format = PR_FMT_PS;
if (filter_index == 3 || filter_index == 4 || filter_index == 5 || filter_index == 6)
pkt_fmt_enable = FALSE;
else
pkt_fmt_enable = TRUE;
for (i = EWFD_PKT_FORMAT_GB; i <= EWFD_PKT_NEW_PAGE_CB; i++) {
cur_ctrl = GetDlgItem(ef_hwnd, i);
EnableWindow(cur_ctrl, pkt_fmt_enable);
}
break;
case CDN_HELP:
topic_action(HELP_EXPORT_FILE_WIN32_DIALOG);
break;
default:
break;
}
break;
default:
break;
}
return 0;
}
/*
* Editor modelines
*
* Local Variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* ex: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/