Have "All Capture Files" match only capture files.
[metze/wireshark/wip.git] / ui / win32 / file_dlg_win32.c
1 /* file_dlg_win32.c
2  * Native Windows file dialog routines
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 2004 Gerald Combs
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "config.h"
24
25 #include <tchar.h>
26 #include <stdlib.h>
27 #include <fcntl.h>
28
29 #include <windows.h>
30 #include <commdlg.h>
31 #include <richedit.h>
32 #include <strsafe.h>
33
34 #include "file.h"
35
36 #include "wsutil/file_util.h"
37 #include "wsutil/str_util.h"
38 #include "wsutil/unicode-utils.h"
39
40 #include "wsutil/filesystem.h"
41 #include "epan/prefs.h"
42
43 #include "epan/color_filters.h"
44
45 #include "ui/alert_box.h"
46 #include "ui/help_url.h"
47 #include "ui/last_open_dir.h"
48 #include "ui/simple_dialog.h"
49 #include "ui/ssl_key_export.h"
50 #include "ui/util.h"
51 #include "ui/ui_util.h"
52 #include "ui/all_files_wildcard.h"
53
54 #include "file_dlg_win32.h"
55
56 #define FILE_OPEN_DEFAULT 1 /* All Files */
57
58 #define FILE_MERGE_DEFAULT FILE_OPEN_DEFAULT
59
60 #define FILE_TYPES_EXPORT \
61     _T("Plain text (*.txt)\0")                           _T("*.txt\0")   \
62     _T("PostScript (*.ps)\0")                            _T("*.ps\0")    \
63     _T("CSV (Comma Separated Values summary) (*.csv)\0") _T("*.csv\0")   \
64     _T("PSML (XML packet summary) (*.psml)\0")           _T("*.psml\0")  \
65     _T("PDML (XML packet detail) (*.pdml)\0")            _T("*.pdml\0")  \
66     _T("C Arrays (packet bytes) (*.c)\0")                _T("*.c\0")     \
67     _T("JSON (*.json)\0")                                _T("*.json\0")
68
69 #define FILE_TYPES_RAW \
70     _T("Raw data (*.bin, *.dat, *.raw)\0")               _T("*.bin;*.dat;*.raw\0") \
71     _T("All Files (") _T(ALL_FILES_WILDCARD) _T(")\0")   _T(ALL_FILES_WILDCARD) _T("\0")
72
73 #define FILE_RAW_DEFAULT 1
74
75 #define FILE_TYPES_SSLKEYS \
76     _T("SSL Session Keys (*.keys)\0")                    _T("*.keys\0") \
77     _T("All Files (") _T(ALL_FILES_WILDCARD) _T(")\0")   _T(ALL_FILES_WILDCARD) _T("\0")
78
79 #define FILE_SSLKEYS_DEFAULT 1
80
81 #define FILE_TYPES_COLOR \
82     _T("Text Files (*.txt)\0")                           _T("*.txt\0")   \
83     _T("All Files (") _T(ALL_FILES_WILDCARD) _T(")\0")   _T(ALL_FILES_WILDCARD) _T("\0")
84
85 #define FILE_DEFAULT_COLOR 2
86
87 static UINT_PTR CALLBACK open_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
88 static UINT_PTR CALLBACK save_as_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
89 static UINT_PTR CALLBACK save_as_statstree_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
90 static UINT_PTR CALLBACK export_specified_packets_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
91 static UINT_PTR CALLBACK merge_file_hook_proc(HWND mf_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
92 static UINT_PTR CALLBACK export_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
93 static UINT_PTR CALLBACK export_raw_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
94 static UINT_PTR CALLBACK export_sslkeys_file_hook_proc(HWND of_hwnd, UINT ui_msg, WPARAM w_param, LPARAM l_param);
95 static void range_update_dynamics(HWND sf_hwnd, packet_range_t *range);
96 static void range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range);
97 static void range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t *range);
98
99 static TCHAR *build_file_open_type_list(void);
100 static TCHAR *build_file_save_type_list(GArray *savable_file_types);
101
102 static int             g_filetype;
103 static gboolean        g_compressed;
104 static packet_range_t *g_range;
105 static capture_file   *g_cf;
106 static merge_action_e  g_merge_action;
107 static print_args_t    print_args;
108 /* XXX - The reason g_sf_hwnd exists is so that we can call
109  *       range_update_dynamics() from anywhere; it's currently
110  *       static, but if we move to using the native Windows
111  *       print dialog and put range widgets in it as well,
112  *       it might be moved to a separate file.
113  *
114  *       However, the save file dialog hogs the foreground, so
115  *       this may not be necessary (and, in fact, the file dialogs
116  *       should arguably be modal to the window for the file
117  *       being opened/saved/etc.).
118  */
119 static HWND  g_sf_hwnd = NULL;
120 static char *g_dfilter_str = NULL;
121 static unsigned int g_format_type = WTAP_TYPE_AUTO;
122
123 static int
124 win32_get_ofnsize()
125 {
126     gboolean bVerGE5 = FALSE;
127     int ofnsize;
128     /* Remarks on OPENFILENAME_SIZE_VERSION_400:
129     *
130     * MSDN states that OPENFILENAME_SIZE_VERSION_400 should be used with
131     * WINVER and _WIN32_WINNT >= 0x0500.
132     * Unfortunately all these are compiler constants, while the underlying is a
133     * problem based is a length check of the runtime version used.
134     *
135     * Instead of using OPENFILENAME_SIZE_VERSION_400, just malloc
136     * the OPENFILENAME size plus 12 bytes.
137     * These 12 bytes are the difference between the two versions of this struct.
138     *
139     * Interestingly this fixes a bug, so the places bar e.g. "My Documents"
140     * is displayed - which wasn't the case with the former implementation.
141     *
142     * XXX - It's unclear if this length+12 works on all supported platforms,
143     * NT4 is the question here. However, even if it fails, we must calculate
144     * the length based on the runtime, not the compiler version anyway ...
145     */
146     /* This assumption does not work when compiling with MSVC2008EE as
147     * the open dialog window does not appear.
148     * Instead detect Windows version at runtime and choose size accordingly */
149 #if (_MSC_VER >= 1500)
150     /*
151     * On VS2103, GetVersionEx is deprecated. Microsoft recommend to
152     * use VerifyVersionInfo instead
153     */
154 #if (_MSC_VER >= 1800)
155     OSVERSIONINFOEX osvi;
156     DWORDLONG dwlConditionMask = 0;
157     int op = VER_GREATER_EQUAL;
158     /* Initialize the OSVERSIONINFOEX structure. */
159     SecureZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
160     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
161     osvi.dwMajorVersion = 5;
162     /* Initialize the condition mask. */
163     VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op);
164     /* Perform the test. */
165     bVerGE5=VerifyVersionInfo(
166         &osvi,
167         VER_MAJORVERSION,
168         dwlConditionMask);
169 #else
170     OSVERSIONINFO osvi;
171     SecureZeroMemory(&osvi, sizeof(OSVERSIONINFO));
172     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
173     GetVersionEx(&osvi);
174     bVerGE5 = (osvi.dwMajorVersion >= 5);
175 #endif /* _MSC_VER >= 1800 */
176     ofnsize = (bVerGE5)?sizeof(OPENFILENAME):OPENFILENAME_SIZE_VERSION_400;
177 #else
178     ofnsize = sizeof(OPENFILENAME)+12;
179 #endif /* _MSC_VER >= 1500 */
180     return ofnsize;
181 }
182 /*
183  * According to http://msdn.microsoft.com/en-us/library/bb776913.aspx
184  * we should use IFileOpenDialog and IFileSaveDialog on Windows Vista
185  * and later.
186  */
187
188 gboolean
189 win32_open_file (HWND h_wnd, GString *file_name, unsigned int *type, GString *display_filter) {
190     OPENFILENAME *ofn;
191     TCHAR file_name16[MAX_PATH] = _T("");
192     int ofnsize;
193     gboolean gofn_ok;
194
195     if (!file_name || !display_filter)
196         return FALSE;
197
198     if (file_name->len > 0) {
199         StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
200     }
201
202     if (display_filter->len > 0) {
203         g_dfilter_str = g_strdup(display_filter->str);
204     } else if (g_dfilter_str) {
205         g_free(g_dfilter_str);
206         g_dfilter_str = NULL;
207     }
208     ofnsize = win32_get_ofnsize();
209     ofn = g_malloc0(ofnsize);
210
211     ofn->lStructSize = ofnsize;
212     ofn->hwndOwner = h_wnd;
213     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
214     ofn->lpstrFilter = build_file_open_type_list();
215     ofn->lpstrCustomFilter = NULL;
216     ofn->nMaxCustFilter = 0;
217     ofn->nFilterIndex = FILE_OPEN_DEFAULT;
218     ofn->lpstrFile = file_name16;
219     ofn->nMaxFile = MAX_PATH;
220     ofn->lpstrFileTitle = NULL;
221     ofn->nMaxFileTitle = 0;
222     if (prefs.gui_fileopen_style == FO_STYLE_SPECIFIED && prefs.gui_fileopen_dir[0] != '\0') {
223         ofn->lpstrInitialDir = utf_8to16(prefs.gui_fileopen_dir);
224     } else {
225         ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
226     }
227     ofn->lpstrTitle = _T("Wireshark: Open Capture File");
228     ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER     |
229                  OFN_NOCHANGEDIR  | OFN_FILEMUSTEXIST  | OFN_HIDEREADONLY |
230                  OFN_ENABLEHOOK   | OFN_SHOWHELP;
231     ofn->lpstrDefExt = NULL;
232     ofn->lpfnHook = open_file_hook_proc;
233     ofn->lpTemplateName = _T("WIRESHARK_OPENFILENAME_TEMPLATE");
234
235     gofn_ok = GetOpenFileName(ofn);
236
237     if (gofn_ok) {
238         g_string_printf(file_name, "%s", utf_16to8(file_name16));
239         g_string_printf(display_filter, "%s", g_dfilter_str ? g_dfilter_str : "");
240         *type = g_format_type;
241     }
242
243     g_free( (void *) ofn->lpstrFilter);
244     g_free( (void *) ofn);
245     g_free(g_dfilter_str);
246     g_dfilter_str = NULL;
247     return gofn_ok;
248 }
249
250 check_savability_t
251 win32_check_save_as_with_comments(HWND parent, capture_file *cf, int file_type)
252 {
253     guint32        comment_types;
254     gint           response;
255
256     /* What types of comments do we have? */
257     comment_types = cf_comment_types(cf);
258
259     /* Does the file's format support all the comments we have? */
260     if (wtap_dump_supports_comment_types(file_type, comment_types)) {
261         /* Yes.  Let the save happen; we can save all the comments, so
262            there's no need to delete them. */
263         return SAVE;
264     }
265
266     /* No. Are there formats in which we can write this file that
267        supports all the comments in this file? */
268     if (wtap_dump_can_write(cf->linktypes, comment_types)) {
269         /* Yes.  Offer the user a choice of "Save in a format that
270            supports comments", "Discard comments and save in the
271            format you selected", or "Cancel", meaning "don't bother
272            saving the file at all".
273
274            XXX - given that we no longer support releases prior to
275            Windows Vista, we should use a task dialog:
276
277                https://msdn.microsoft.com/en-us/library/windows/desktop/ff486057(v=vs.85).aspx
278
279            created with TaskDialogIndirect():
280
281                https://msdn.microsoft.com/en-us/library/windows/desktop/bb760544(v=vs.85).aspx
282
283            because the TASKDIALOGCONFIG structure
284
285                https://msdn.microsoft.com/en-us/library/windows/desktop/bb787473(v=vs.85).aspx
286
287            supports adding custom buttons, with custom labels, unlike
288            a MessageBox(), which doesn't appear to offer a clean way to
289            do that. */
290         response = MessageBox(parent,
291   _T("The capture has comments, but the file format you chose ")
292   _T("doesn't support comments.  Do you want to discard the comments ")
293   _T("and save in the format you chose?"),
294                               _T("Wireshark: Save File As"),
295                               MB_YESNOCANCEL|MB_ICONWARNING|MB_DEFBUTTON2);
296     } else {
297         /* No.  Offer the user a choice of "Discard comments and
298            save in the format you selected" or "Cancel".
299
300            XXX - see rant above. */
301         response = MessageBox(parent,
302   _T("The capture has comments, but no file format in which it ")
303   _T("can be saved supports comments.  Do you want to discard ")
304   _T("the comments and save in the format you chose?"),
305                               _T("Wireshark: Save File As"),
306                               MB_OKCANCEL|MB_ICONWARNING|MB_DEFBUTTON2);
307     }
308
309     switch (response) {
310
311     case IDNO: /* "No" means "Save in another format" in the first dialog */
312         /* OK, the only other format we support is pcap-ng.  Make that
313            the one and only format in the combo box, and return to
314            let the user continue with the dialog.
315
316            XXX - removing all the formats from the combo box will clear
317            the compressed checkbox; get the current value and restore
318            it.
319
320            XXX - we know pcap-ng can be compressed; if we ever end up
321            supporting saving comments in a format that *can't* be
322            compressed, such as NetMon format, we must check this. */
323         /* XXX - need a compressed checkbox here! */
324         return SAVE_IN_ANOTHER_FORMAT;
325
326     case IDYES: /* "Yes" means "Discard comments and save" in the first dialog */
327     case IDOK:  /* "OK" means "Discard comments and save" in the second dialog */
328         /* Save without the comments and, if that succeeds, delete the
329            comments. */
330         return SAVE_WITHOUT_COMMENTS;
331
332     case IDCANCEL:
333     default:
334         /* Just give up. */
335         return CANCELLED;
336     }
337 }
338
339 gboolean
340 win32_save_as_file(HWND h_wnd, capture_file *cf, GString *file_name, int *file_type,
341                    gboolean *compressed, gboolean must_support_all_comments)
342 {
343     guint32 required_comment_types;
344     GArray *savable_file_types;
345     OPENFILENAME *ofn;
346     TCHAR  file_name16[MAX_PATH] = _T("");
347     int    ofnsize;
348     gboolean gsfn_ok;
349
350     if (!file_name || !file_type || !compressed)
351         return FALSE;
352
353     if (file_name->len > 0) {
354         StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
355     }
356
357     /* What types of comments do we have to support? */
358     if (must_support_all_comments)
359         required_comment_types = cf_comment_types(cf); /* all the ones the file has */
360     else
361         required_comment_types = 0; /* none of them */
362
363     savable_file_types = wtap_get_savable_file_types_subtypes(cf->cd_t,
364                                                               cf->linktypes,
365                                                               required_comment_types);
366     if (savable_file_types == NULL)
367         return FALSE;  /* shouldn't happen - the "Save As..." item should be disabled if we can't save the file */
368     g_compressed = FALSE;
369
370     ofnsize = win32_get_ofnsize();
371     ofn = g_malloc0(ofnsize);
372
373     ofn->lStructSize = ofnsize;
374     ofn->hwndOwner = h_wnd;
375     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
376     ofn->lpstrFilter = build_file_save_type_list(savable_file_types);
377     ofn->lpstrCustomFilter = NULL;
378     ofn->nMaxCustFilter = 0;
379     ofn->nFilterIndex = 1;  /* the first entry is the best match; 1-origin indexing */
380     ofn->lpstrFile = file_name16;
381     ofn->nMaxFile = MAX_PATH;
382     ofn->lpstrFileTitle = NULL;
383     ofn->nMaxFileTitle = 0;
384     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
385     ofn->lpstrTitle = _T("Wireshark: Save file as");
386     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
387                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
388                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
389     ofn->lpstrDefExt = NULL;
390     ofn->lCustData = (LPARAM) cf;
391     ofn->lpfnHook = save_as_file_hook_proc;
392     ofn->lpTemplateName = _T("WIRESHARK_SAVEASFILENAME_TEMPLATE");
393
394     gsfn_ok = GetSaveFileName(ofn);
395
396     if (gsfn_ok) {
397         g_string_printf(file_name, "%s", utf_16to8(file_name16));
398         /* What file format was specified? */
399         *file_type = g_array_index(savable_file_types, int, ofn->nFilterIndex - 1);
400         *compressed = g_compressed;
401     } else {
402         /* User cancelled or closed the dialog, or an error occurred. */
403         if (CommDlgExtendedError() != 0) {
404             /* XXX - pop up some error here. FNERR_INVALIDFILENAME
405              * might be a user error; if so, they should know about
406              * it. For now we force a do-over.
407              */
408             g_string_truncate(file_name, 0);
409             gsfn_ok = TRUE;
410         }
411     }
412
413     g_sf_hwnd = NULL;
414     g_array_free(savable_file_types, TRUE);
415     g_free( (void *) ofn->lpstrFilter);
416     g_free( (void *) ofn);
417     return gsfn_ok;
418 }
419
420 gboolean win32_save_as_statstree(HWND h_wnd, GString *file_name, int *file_type)
421 {
422     OPENFILENAME *ofn;
423     TCHAR  file_name16[MAX_PATH] = _T("");
424     int    ofnsize;
425     gboolean gsfn_ok;
426 #if (_MSC_VER >= 1500)
427     OSVERSIONINFO osvi;
428 #endif
429
430     if (!file_name || !file_type)
431         return FALSE;
432
433     if (file_name->len > 0) {
434         StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
435     }
436
437     /* see OPENFILENAME comment in win32_open_file */
438 #if (_MSC_VER >= 1500)
439     SecureZeroMemory(&osvi, sizeof(OSVERSIONINFO));
440     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
441     GetVersionEx(&osvi);
442     if (osvi.dwMajorVersion >= 5) {
443         ofnsize = sizeof(OPENFILENAME);
444     } else {
445         ofnsize = OPENFILENAME_SIZE_VERSION_400;
446     }
447 #else
448     ofnsize = sizeof(OPENFILENAME) + 12;
449 #endif
450     ofn = g_malloc0(ofnsize);
451
452     ofn->lStructSize = ofnsize;
453     ofn->hwndOwner = h_wnd;
454     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
455     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");
456     ofn->lpstrCustomFilter = NULL;
457     ofn->nMaxCustFilter = 0;
458     ofn->nFilterIndex = 1;  /* the first entry is the best match; 1-origin indexing */
459     ofn->lpstrFile = file_name16;
460     ofn->nMaxFile = MAX_PATH;
461     ofn->lpstrFileTitle = NULL;
462     ofn->nMaxFileTitle = 0;
463     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
464     ofn->lpstrTitle = _T("Wireshark: Save stats tree as ...");
465     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER        |
466                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
467                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
468     ofn->lpstrDefExt = NULL;
469     ofn->lpfnHook = save_as_statstree_hook_proc;
470     ofn->lpTemplateName = _T("WIRESHARK_SAVEASSTATSTREENAME_TEMPLATE");
471
472     gsfn_ok = GetSaveFileName(ofn);
473
474     if (gsfn_ok) {
475         g_string_printf(file_name, "%s", utf_16to8(file_name16));
476         /* What file format was specified? */
477         *file_type = ofn->nFilterIndex - 1;
478     }
479
480     g_sf_hwnd = NULL;
481     g_free( (void *) ofn);
482     return gsfn_ok;
483 }
484
485
486 gboolean
487 win32_export_specified_packets_file(HWND h_wnd, capture_file *cf,
488                                     GString *file_name,
489                                     int *file_type,
490                                     gboolean *compressed,
491                                     packet_range_t *range) {
492     GArray *savable_file_types;
493     OPENFILENAME *ofn;
494     TCHAR  file_name16[MAX_PATH] = _T("");
495     int    ofnsize;
496     gboolean gsfn_ok;
497
498     if (!file_name || !file_type || !compressed || !range)
499         return FALSE;
500
501     if (file_name->len > 0) {
502         StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
503     }
504
505     savable_file_types = wtap_get_savable_file_types_subtypes(cf->cd_t,
506                                                               cf->linktypes, 0);
507     if (savable_file_types == NULL)
508         return FALSE;  /* shouldn't happen - the "Save As..." item should be disabled if we can't save the file */
509
510     g_range = range;
511     g_cf = cf;
512     g_compressed = FALSE;
513
514     ofnsize = win32_get_ofnsize();
515     ofn = g_malloc0(ofnsize);
516
517     ofn->lStructSize = ofnsize;
518     ofn->hwndOwner = h_wnd;
519     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
520     ofn->lpstrFilter = build_file_save_type_list(savable_file_types);
521     ofn->lpstrCustomFilter = NULL;
522     ofn->nMaxCustFilter = 0;
523     ofn->nFilterIndex = 1;  /* the first entry is the best match; 1-origin indexing */
524     ofn->lpstrFile = file_name16;
525     ofn->nMaxFile = MAX_PATH;
526     ofn->lpstrFileTitle = NULL;
527     ofn->nMaxFileTitle = 0;
528     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
529     ofn->lpstrTitle = _T("Wireshark: Export Specified Packets");
530     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
531                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
532                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
533     ofn->lpstrDefExt = NULL;
534     ofn->lCustData = (LPARAM) cf;
535     ofn->lpfnHook = export_specified_packets_file_hook_proc;
536     ofn->lpTemplateName = _T("WIRESHARK_EXPORT_SPECIFIED_PACKETS_FILENAME_TEMPLATE");
537
538     gsfn_ok = GetSaveFileName(ofn);
539
540     if (gsfn_ok) {
541         g_string_printf(file_name, "%s", utf_16to8(file_name16));
542         /* What file format was specified? */
543         *file_type = g_array_index(savable_file_types, int, ofn->nFilterIndex - 1);
544         *compressed = g_compressed;
545     } else {
546         /* User cancelled or closed the dialog, or an error occurred. */
547         if (CommDlgExtendedError() != 0) {
548             /* XXX - pop up some error here. FNERR_INVALIDFILENAME
549              * might be a user error; if so, they should know about
550              * it. For now we force a do-over.
551              */
552             g_string_truncate(file_name, 0);
553             gsfn_ok = TRUE;
554         }
555     }
556
557     g_sf_hwnd = NULL;
558     g_range = NULL;
559     g_cf = NULL;
560     g_array_free(savable_file_types, TRUE);
561     g_free( (void *) ofn->lpstrFilter);
562     g_free( (void *) ofn);
563     return gsfn_ok;
564 }
565
566
567 gboolean
568 win32_merge_file (HWND h_wnd, GString *file_name, GString *display_filter, int *merge_type) {
569     OPENFILENAME *ofn;
570     TCHAR         file_name16[MAX_PATH] = _T("");
571     int           ofnsize;
572     gboolean gofn_ok;
573
574     if (!file_name || !display_filter || !merge_type)
575         return FALSE;
576
577     if (file_name->len > 0) {
578         StringCchCopy(file_name16, MAX_PATH, utf_8to16(file_name->str));
579     }
580
581     if (display_filter->len > 0) {
582         g_dfilter_str = g_strdup(display_filter->str);
583     } else if (g_dfilter_str) {
584         g_free(g_dfilter_str);
585         g_dfilter_str = NULL;
586     }
587
588     ofnsize = win32_get_ofnsize();
589     ofn = g_malloc0(ofnsize);
590
591     ofn->lStructSize = ofnsize;
592     ofn->hwndOwner = h_wnd;
593     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
594     ofn->lpstrFilter = build_file_open_type_list();
595     ofn->lpstrCustomFilter = NULL;
596     ofn->nMaxCustFilter = 0;
597     ofn->nFilterIndex = FILE_MERGE_DEFAULT;
598     ofn->lpstrFile = file_name16;
599     ofn->nMaxFile = MAX_PATH;
600     ofn->lpstrFileTitle = NULL;
601     ofn->nMaxFileTitle = 0;
602     if (prefs.gui_fileopen_style == FO_STYLE_SPECIFIED && prefs.gui_fileopen_dir[0] != '\0') {
603         ofn->lpstrInitialDir = utf_8to16(prefs.gui_fileopen_dir);
604     } else {
605         ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
606     }
607     ofn->lpstrTitle = _T("Wireshark: Merge with capture file");
608     ofn->Flags = OFN_ENABLESIZING | OFN_ENABLETEMPLATE | OFN_EXPLORER     |
609                  OFN_NOCHANGEDIR  | OFN_FILEMUSTEXIST  | OFN_HIDEREADONLY |
610                  OFN_ENABLEHOOK   | OFN_SHOWHELP;
611     ofn->lpstrDefExt = NULL;
612     ofn->lpfnHook = merge_file_hook_proc;
613     ofn->lpTemplateName = _T("WIRESHARK_MERGEFILENAME_TEMPLATE");
614
615     gofn_ok = GetOpenFileName(ofn);
616
617     if (gofn_ok) {
618         g_string_printf(file_name, "%s", utf_16to8(file_name16));
619         g_string_printf(display_filter, "%s", g_dfilter_str ? g_dfilter_str : "");
620
621         switch (g_merge_action) {
622             case merge_append:
623                 *merge_type = 1;
624                 break;
625             case merge_chrono:
626                 *merge_type = 0;
627                 break;
628             case merge_prepend:
629                 *merge_type = -1;
630                 break;
631             default:
632                 g_assert_not_reached();
633         }
634     }
635
636     g_free( (void *) ofn->lpstrFilter);
637     g_free( (void *) ofn);
638     g_free(g_dfilter_str);
639     g_dfilter_str = NULL;
640     return gofn_ok;
641 }
642
643 void
644 win32_export_file(HWND h_wnd, capture_file *cf, export_type_e export_type) {
645     OPENFILENAME     *ofn;
646     TCHAR             file_name[MAX_PATH] = _T("");
647     char             *dirname;
648     cf_print_status_t status;
649     int               ofnsize;
650
651     g_cf = cf;
652
653     ofnsize = win32_get_ofnsize();
654     ofn = g_malloc0(ofnsize);
655
656     ofn->lStructSize = ofnsize;
657     ofn->hwndOwner = h_wnd;
658     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
659     ofn->lpstrFilter = FILE_TYPES_EXPORT;
660     ofn->lpstrCustomFilter = NULL;
661     ofn->nMaxCustFilter = 0;
662     ofn->nFilterIndex = export_type;
663     ofn->lpstrFile = file_name;
664     ofn->nMaxFile = MAX_PATH;
665     ofn->lpstrFileTitle = NULL;
666     ofn->nMaxFileTitle = 0;
667     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
668     ofn->lpstrTitle = _T("Wireshark: Export File");
669     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
670                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
671                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
672     ofn->lpstrDefExt = NULL;
673     ofn->lCustData = (LPARAM) cf;
674     ofn->lpfnHook = export_file_hook_proc;
675     ofn->lpTemplateName = _T("WIRESHARK_EXPORTFILENAME_TEMPLATE");
676
677     /* Fill in our print (and export) args */
678
679     print_args.format              = PR_FMT_TEXT;
680     print_args.to_file             = TRUE;
681     print_args.cmd                 = NULL;
682     print_args.print_summary       = TRUE;
683     print_args.print_col_headings  = TRUE;
684     print_args.print_dissections   = print_dissections_as_displayed;
685     print_args.print_hex           = FALSE;
686     print_args.print_formfeed      = FALSE;
687
688     if (GetSaveFileName(ofn)) {
689         print_args.file = utf_16to8(file_name);
690         switch (ofn->nFilterIndex) {
691             case export_type_text:      /* Text */
692                 print_args.stream = print_stream_text_new(TRUE, print_args.file);
693                 if (print_args.stream == NULL) {
694                     open_failure_alert_box(print_args.file, errno, TRUE);
695                     g_free( (void *) ofn);
696                     return;
697                 }
698                 status = cf_print_packets(cf, &print_args, TRUE);
699                 break;
700             case export_type_ps:        /* PostScript (r) */
701                 print_args.stream = print_stream_ps_new(TRUE, print_args.file);
702                 if (print_args.stream == NULL) {
703                     open_failure_alert_box(print_args.file, errno, TRUE);
704                     g_free( (void *) ofn);
705                     return;
706                 }
707                 status = cf_print_packets(cf, &print_args, TRUE);
708                 break;
709             case export_type_csv:       /* CSV */
710                 status = cf_write_csv_packets(cf, &print_args);
711                 break;
712             case export_type_carrays:   /* C Arrays */
713                 status = cf_write_carrays_packets(cf, &print_args);
714                 break;
715             case export_type_psml:      /* PSML */
716                 status = cf_write_psml_packets(cf, &print_args);
717                 break;
718             case export_type_pdml:      /* PDML */
719                 status = cf_write_pdml_packets(cf, &print_args);
720                 break;
721             case export_type_json:      /* JSON */
722                 status = cf_write_json_packets(cf, &print_args);
723                 break;
724             default:
725                 g_free( (void *) ofn);
726                 return;
727         }
728
729         switch (status) {
730             case CF_PRINT_OK:
731                 break;
732             case CF_PRINT_OPEN_ERROR:
733                 open_failure_alert_box(print_args.file, errno, TRUE);
734                 break;
735             case CF_PRINT_WRITE_ERROR:
736                 write_failure_alert_box(print_args.file, errno);
737                 break;
738         }
739         /* Save the directory name for future file dialogs. */
740         dirname = get_dirname(utf_16to8(file_name));  /* Overwrites cf_name */
741         set_last_open_dir(dirname);
742     }
743
744     g_cf = NULL;
745     g_free( (void *) ofn);
746 }
747
748 void
749 win32_export_raw_file(HWND h_wnd, capture_file *cf) {
750     OPENFILENAME *ofn;
751     TCHAR         file_name[MAX_PATH] = _T("");
752     char         *dirname;
753     const guint8 *data_p;
754     char         *file_name8;
755     int           fd;
756     int           ofnsize;
757
758     if (!cf->finfo_selected) {
759         /* This shouldn't happen */
760         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No bytes were selected.");
761         return;
762     }
763
764     ofnsize = win32_get_ofnsize();
765     ofn = g_malloc0(ofnsize);
766
767     ofn->lStructSize = ofnsize;
768     ofn->hwndOwner = h_wnd;
769     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
770     ofn->lpstrFilter = FILE_TYPES_RAW;
771     ofn->lpstrCustomFilter = NULL;
772     ofn->nMaxCustFilter = 0;
773     ofn->nFilterIndex = FILE_RAW_DEFAULT;
774     ofn->lpstrFile = file_name;
775     ofn->nMaxFile = MAX_PATH;
776     ofn->lpstrFileTitle = NULL;
777     ofn->nMaxFileTitle = 0;
778     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
779     ofn->lpstrTitle = _T("Wireshark: Export Raw Data");
780     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
781                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
782                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
783     ofn->lpstrDefExt = NULL;
784     ofn->lCustData = cf->finfo_selected->length;
785     ofn->lpfnHook = export_raw_file_hook_proc;
786     ofn->lpTemplateName = _T("WIRESHARK_EXPORTRAWFILENAME_TEMPLATE");
787
788     /*
789      * XXX - The GTK+ code uses get_byte_view_data_and_length().  We just
790      * grab the info from cf->finfo_selected.  Which is more "correct"?
791      */
792
793     if (GetSaveFileName(ofn)) {
794         g_free( (void *) ofn);
795         file_name8 = utf_16to8(file_name);
796         data_p = tvb_get_ptr(cf->finfo_selected->ds_tvb, 0, -1) +
797                 cf->finfo_selected->start;
798         fd = ws_open(file_name8, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
799         if (fd == -1) {
800             open_failure_alert_box(file_name8, errno, TRUE);
801             return;
802         }
803         if (ws_write(fd, data_p, cf->finfo_selected->length) < 0) {
804             write_failure_alert_box(file_name8, errno);
805             ws_close(fd);
806             return;
807         }
808         if (ws_close(fd) < 0) {
809             write_failure_alert_box(file_name8, errno);
810             return;
811         }
812
813         /* Save the directory name for future file dialogs. */
814         dirname = get_dirname(file_name8);  /* Overwrites cf_name */
815         set_last_open_dir(dirname);
816     } else {
817         g_free( (void *) ofn);
818     }
819 }
820
821 void
822 win32_export_sslkeys_file(HWND h_wnd) {
823     OPENFILENAME *ofn;
824     TCHAR         file_name[MAX_PATH] = _T("");
825     char         *dirname;
826     gchar        *keylist = NULL;
827     char         *file_name8;
828     int           fd;
829     int           ofnsize;
830     int           keylist_size;
831
832     keylist_size = ssl_session_key_count();
833     if (keylist_size==0) {
834         /* This shouldn't happen */
835         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No SSL Session Keys to export.");
836         return;
837     }
838
839     ofnsize = win32_get_ofnsize();
840     ofn = g_malloc0(ofnsize);
841
842     ofn->lStructSize = ofnsize;
843     ofn->hwndOwner = h_wnd;
844     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
845     ofn->lpstrFilter = FILE_TYPES_SSLKEYS;
846     ofn->lpstrCustomFilter = NULL;
847     ofn->nMaxCustFilter = 0;
848     ofn->nFilterIndex = FILE_SSLKEYS_DEFAULT;
849     ofn->lpstrFile = file_name;
850     ofn->nMaxFile = MAX_PATH;
851     ofn->lpstrFileTitle = NULL;
852     ofn->nMaxFileTitle = 0;
853     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
854     ofn->lpstrTitle = _T("Wireshark: Export SSL Session Keys");
855     ofn->Flags = OFN_ENABLESIZING  | OFN_ENABLETEMPLATE  | OFN_EXPLORER     |
856                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
857                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK      | OFN_SHOWHELP;
858     ofn->lpstrDefExt = NULL;
859     ofn->lCustData = keylist_size;
860     ofn->lpfnHook = export_sslkeys_file_hook_proc;
861     ofn->lpTemplateName = _T("WIRESHARK_EXPORTSSLKEYSFILENAME_TEMPLATE");
862
863     if (GetSaveFileName(ofn)) {
864         g_free( (void *) ofn);
865         file_name8 = utf_16to8(file_name);
866         keylist = ssl_export_sessions();
867         fd = ws_open(file_name8, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666);
868         if (fd == -1) {
869             open_failure_alert_box(file_name8, errno, TRUE);
870             g_free(keylist);
871             return;
872         }
873         /*
874          * Thanks, Microsoft, for not using size_t for the third argument to
875          * _write().  Presumably this string will be <= 4GiB long....
876          */
877         if (ws_write(fd, keylist, (unsigned int)strlen(keylist)) < 0) {
878             write_failure_alert_box(file_name8, errno);
879             ws_close(fd);
880             g_free(keylist);
881             return;
882         }
883         if (ws_close(fd) < 0) {
884             write_failure_alert_box(file_name8, errno);
885             g_free(keylist);
886             return;
887         }
888
889         /* Save the directory name for future file dialogs. */
890         dirname = get_dirname(file_name8);  /* Overwrites cf_name */
891         set_last_open_dir(dirname);
892     } else {
893         g_free( (void *) ofn);
894     }
895     g_free(keylist);
896 }
897
898 void
899 win32_export_color_file(HWND h_wnd, capture_file *cf, gpointer filter_list) {
900     OPENFILENAME *ofn;
901     TCHAR  file_name[MAX_PATH] = _T("");
902     gchar *dirname;
903     int    ofnsize;
904     gchar *err_msg = NULL;
905
906     ofnsize = win32_get_ofnsize();
907     ofn = g_malloc0(ofnsize);
908
909     ofn->lStructSize = ofnsize;
910     ofn->hwndOwner = h_wnd;
911     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
912     ofn->lpstrFilter = FILE_TYPES_COLOR;
913     ofn->lpstrCustomFilter = NULL;
914     ofn->nMaxCustFilter = 0;
915     ofn->nFilterIndex = FILE_DEFAULT_COLOR;
916     ofn->lpstrFile = file_name;
917     ofn->nMaxFile = MAX_PATH;
918     ofn->lpstrFileTitle = NULL;
919     ofn->nMaxFileTitle = 0;
920     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
921     ofn->lpstrTitle = _T("Wireshark: Export Color Filters");
922     ofn->Flags = OFN_ENABLESIZING  | OFN_EXPLORER        |
923                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
924                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
925     ofn->lpstrDefExt = NULL;
926     ofn->lpfnHook = NULL;
927     ofn->lpTemplateName = NULL;
928
929     g_filetype = cf->cd_t;
930
931     /* XXX - Support marked filters */
932     if (GetSaveFileName(ofn)) {
933         g_free( (void *) ofn);
934         if (!color_filters_export(utf_16to8(file_name), filter_list, FALSE /* all filters */, &err_msg))
935         {
936             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
937             g_free(err_msg);
938             return;
939         }
940
941         /* Save the directory name for future file dialogs. */
942         dirname = get_dirname(utf_16to8(file_name));  /* Overwrites cf_name */
943         set_last_open_dir(dirname);
944     } else {
945         g_free( (void *) ofn);
946     }
947 }
948
949 void
950 win32_import_color_file(HWND h_wnd, gpointer color_filters) {
951     OPENFILENAME *ofn;
952     TCHAR  file_name[MAX_PATH] = _T("");
953     gchar *dirname;
954     int    ofnsize;
955     gchar *err_msg = NULL;
956
957     ofnsize = win32_get_ofnsize();
958     ofn = g_malloc0(ofnsize);
959
960     ofn->lStructSize = ofnsize;
961     ofn->hwndOwner = h_wnd;
962     ofn->hInstance = (HINSTANCE) GetWindowLongPtr(h_wnd, GWLP_HINSTANCE);
963     ofn->lpstrFilter = FILE_TYPES_COLOR;
964     ofn->lpstrCustomFilter = NULL;
965     ofn->nMaxCustFilter = 0;
966     ofn->nFilterIndex = FILE_DEFAULT_COLOR;
967     ofn->lpstrFile = file_name;
968     ofn->nMaxFile = MAX_PATH;
969     ofn->lpstrFileTitle = NULL;
970     ofn->nMaxFileTitle = 0;
971     ofn->lpstrInitialDir = utf_8to16(get_last_open_dir());
972     ofn->lpstrTitle = _T("Wireshark: Import Color Filters");
973     ofn->Flags = OFN_ENABLESIZING  | OFN_EXPLORER        |
974                  OFN_NOCHANGEDIR   | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY |
975                  OFN_PATHMUSTEXIST | OFN_ENABLEHOOK;
976     ofn->lpstrDefExt = NULL;
977     ofn->lpfnHook = NULL;
978     ofn->lpTemplateName = NULL;
979
980     /* XXX - Support export limited to selected filters */
981     if (GetOpenFileName(ofn)) {
982         g_free( (void *) ofn);
983         if (!color_filters_import(utf_16to8(file_name), color_filters, &err_msg, color_filter_add_cb)) {
984             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_msg);
985             g_free(err_msg);
986             return;
987         }
988
989         /* Save the directory name for future file dialogs. */
990         dirname = get_dirname(utf_16to8(file_name));  /* Overwrites cf_name */
991         set_last_open_dir(dirname);
992     } else {
993         g_free( (void *) ofn);
994     }
995 }
996
997
998 /*
999  * Private routines
1000  */
1001
1002 /** Given a print_args_t struct, update a set of print/export format controls
1003  *  accordingly.
1004  *
1005  * @param dlg_hwnd HWND of the dialog in question.
1006  * @param args Pointer to a print args struct.
1007  */
1008 static void
1009 print_update_dynamic(HWND dlg_hwnd, print_args_t *args) {
1010     HWND cur_ctrl;
1011
1012     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_SUMMARY_CB);
1013     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1014         args->print_summary = TRUE;
1015         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_COL_HEADINGS_CB);
1016         EnableWindow(cur_ctrl, TRUE);
1017         if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1018             args->print_col_headings = TRUE;
1019         else
1020             args->print_col_headings = FALSE;
1021     } else {
1022         args->print_summary = FALSE;
1023         args->print_col_headings = FALSE;
1024         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_COL_HEADINGS_CB);
1025         EnableWindow(cur_ctrl, FALSE);
1026     }
1027
1028     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_CB);
1029     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
1030         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
1031         switch (SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0)) {
1032             case 0:
1033                 args->print_dissections = print_dissections_collapsed;
1034                 break;
1035             case 1:
1036                 args->print_dissections = print_dissections_as_displayed;
1037                 break;
1038             case 2:
1039                 args->print_dissections = print_dissections_expanded;
1040                 break;
1041             default:
1042                 g_assert_not_reached();
1043         }
1044         EnableWindow(cur_ctrl, TRUE);
1045     } else {
1046         args->print_dissections = print_dissections_none;
1047         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
1048         EnableWindow(cur_ctrl, FALSE);
1049     }
1050
1051     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_BYTES_CB);
1052     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1053         args->print_hex = TRUE;
1054     else
1055         args->print_hex = FALSE;
1056
1057     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_NEW_PAGE_CB);
1058     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1059         args->print_formfeed = TRUE;
1060     else
1061         args->print_formfeed = FALSE;
1062 }
1063
1064 static void
1065 format_handle_wm_initdialog(HWND dlg_hwnd, print_args_t *args) {
1066     HWND cur_ctrl;
1067
1068     /* Set the "Packet summary" and "Include column headings" boxes */
1069     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_SUMMARY_CB);
1070     SendMessage(cur_ctrl, BM_SETCHECK, args->print_summary, 0);
1071     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_COL_HEADINGS_CB);
1072     SendMessage(cur_ctrl, BM_SETCHECK, args->print_col_headings, 0);
1073
1074     /* Set the "Packet details" box */
1075     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_CB);
1076     SendMessage(cur_ctrl, BM_SETCHECK, args->print_dissections != print_dissections_none, 0);
1077
1078     /* Set the "Packet details" combo */
1079     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_DETAIL_COMBO);
1080     SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("All collapsed"));
1081     SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("As displayed"));
1082     SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("All expanded"));
1083
1084     switch (args->print_dissections) {
1085         case print_dissections_none:
1086         case print_dissections_collapsed:
1087             SendMessage(cur_ctrl, CB_SETCURSEL, 0, 0);
1088             break;
1089         case print_dissections_as_displayed:
1090             SendMessage(cur_ctrl, CB_SETCURSEL, 1, 0);
1091             break;
1092         case print_dissections_expanded:
1093             SendMessage(cur_ctrl, CB_SETCURSEL, 2, 0);
1094         default:
1095             g_assert_not_reached();
1096     }
1097
1098     /* Set the "Packet bytes" box */
1099     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_BYTES_CB);
1100     SendMessage(cur_ctrl, BM_SETCHECK, args->print_hex, 0);
1101
1102     /* Set the "Each packet on a new page" box */
1103     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_PKT_NEW_PAGE_CB);
1104     SendMessage(cur_ctrl, BM_SETCHECK, args->print_formfeed, 0);
1105
1106     print_update_dynamic(dlg_hwnd, args);
1107 }
1108
1109
1110 #define PREVIEW_STR_MAX      200
1111
1112 /* If preview_file is NULL, disable the elements.  If not, enable and
1113  * show the preview info. */
1114 static gboolean
1115 preview_set_file_info(HWND of_hwnd, gchar *preview_file) {
1116     HWND        cur_ctrl;
1117     int         i;
1118     wtap       *wth;
1119     const struct wtap_pkthdr *phdr;
1120     int         err = 0;
1121     gchar      *err_info;
1122     TCHAR       string_buff[PREVIEW_STR_MAX];
1123     TCHAR       first_buff[PREVIEW_STR_MAX];
1124     gint64      data_offset;
1125     guint       packet = 0;
1126     gint64      filesize;
1127     gchar      *size_str;
1128     time_t      ti_time;
1129     struct tm  *ti_tm;
1130     guint       elapsed_time;
1131     time_t      time_preview;
1132     time_t      time_current;
1133     double      start_time = 0;
1134     double      stop_time = 0;
1135     double      cur_time;
1136     gboolean    is_breaked = FALSE;
1137
1138     for (i = EWFD_PTX_FORMAT; i <= EWFD_PTX_START_ELAPSED; i++) {
1139         cur_ctrl = GetDlgItem(of_hwnd, i);
1140         if (cur_ctrl) {
1141             EnableWindow(cur_ctrl, FALSE);
1142         }
1143     }
1144
1145     for (i = EWFD_PTX_FORMAT; i <= EWFD_PTX_START_ELAPSED; i++) {
1146         cur_ctrl = GetDlgItem(of_hwnd, i);
1147         if (cur_ctrl) {
1148             SetWindowText(cur_ctrl, _T("-"));
1149         }
1150     }
1151
1152     if (preview_file == NULL || strlen(preview_file) < 1) {
1153         return FALSE;
1154     }
1155
1156     /* Format: directory */
1157     cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
1158     if (test_for_directory(preview_file) == EISDIR) {
1159         SetWindowText(cur_ctrl, _T("directory"));
1160         return FALSE;
1161     }
1162
1163     wth = wtap_open_offline(preview_file, WTAP_TYPE_AUTO, &err, &err_info, TRUE);
1164     if (cur_ctrl && wth == NULL) {
1165         if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
1166             SetWindowText(cur_ctrl, _T("unknown file format"));
1167         } else {
1168             SetWindowText(cur_ctrl, _T("error opening file"));
1169         }
1170         return FALSE;
1171     }
1172
1173     /* Success! */
1174     for (i = EWFD_PT_FORMAT; i <= EWFD_PTX_START_ELAPSED; i++) {
1175         cur_ctrl = GetDlgItem(of_hwnd, i);
1176         if (cur_ctrl) {
1177             EnableWindow(cur_ctrl, TRUE);
1178         }
1179     }
1180
1181     /* Format */
1182     cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_FORMAT);
1183     SetWindowText(cur_ctrl, utf_8to16(wtap_file_type_subtype_string(wtap_file_type_subtype(wth))));
1184
1185     /* Size */
1186     filesize = wtap_file_size(wth, &err);
1187     // Windows Explorer uses IEC.
1188     size_str = format_size(filesize, format_size_unit_bytes|format_size_prefix_iec);
1189
1190     time(&time_preview);
1191     while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
1192         phdr = wtap_phdr(wth);
1193         cur_time = nstime_to_sec( (const nstime_t *) &phdr->ts );
1194         if(packet == 0) {
1195             start_time  = cur_time;
1196             stop_time = cur_time;
1197         }
1198         if (cur_time < start_time) {
1199             start_time = cur_time;
1200         }
1201         if (cur_time > stop_time){
1202             stop_time = cur_time;
1203         }
1204         packet++;
1205         if(packet%100 == 0) {
1206             time(&time_current);
1207             if(time_current-time_preview >= (time_t) prefs.gui_fileopen_preview) {
1208                 is_breaked = TRUE;
1209                 break;
1210             }
1211         }
1212     }
1213
1214     if(err != 0) {
1215         utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%s, error after %u packets",
1216             size_str, packet);
1217         g_free(size_str);
1218         cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_SIZE);
1219         SetWindowText(cur_ctrl, string_buff);
1220         wtap_close(wth);
1221         return TRUE;
1222     }
1223
1224     /* Packets */
1225     if(is_breaked) {
1226         utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%s, timed out at %u packets",
1227             size_str, packet);
1228     } else {
1229         utf_8to16_snprintf(string_buff, PREVIEW_STR_MAX, "%s, %u packets",
1230             size_str, packet);
1231     }
1232     g_free(size_str);
1233     cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_SIZE);
1234     SetWindowText(cur_ctrl, string_buff);
1235
1236     /* First packet / elapsed time */
1237     ti_time = (long)start_time;
1238     ti_tm = localtime( &ti_time );
1239     if(ti_tm) {
1240         StringCchPrintf(first_buff, PREVIEW_STR_MAX,
1241                  _T("%04d-%02d-%02d %02d:%02d:%02d"),
1242                  ti_tm->tm_year + 1900,
1243                  ti_tm->tm_mon + 1,
1244                  ti_tm->tm_mday,
1245                  ti_tm->tm_hour,
1246                  ti_tm->tm_min,
1247                  ti_tm->tm_sec);
1248     } else {
1249         StringCchPrintf(first_buff, PREVIEW_STR_MAX, _T("?"));
1250     }
1251
1252     elapsed_time = (unsigned int)(stop_time-start_time);
1253     if(elapsed_time/86400) {
1254         StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%s / %02u days %02u:%02u:%02u"),
1255         first_buff, elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
1256     } else {
1257         StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%s / %02u:%02u:%02u"),
1258         first_buff, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
1259     }
1260     if(is_breaked) {
1261         StringCchPrintf(string_buff, PREVIEW_STR_MAX, _T("%s / unknown"), first_buff);
1262     }
1263     cur_ctrl = GetDlgItem(of_hwnd, EWFD_PTX_START_ELAPSED);
1264     SetWindowText(cur_ctrl, string_buff);
1265
1266     wtap_close(wth);
1267
1268     return TRUE;
1269
1270 }
1271
1272
1273 static char *
1274 filter_tb_get(HWND hwnd) {
1275     TCHAR     *strval = NULL;
1276     gint       len;
1277     char *ret;
1278
1279     /* If filter_text is non-NULL, use it.  Otherwise, grab the text from
1280      * the window */
1281     len = GetWindowTextLength(hwnd);
1282     if (len > 0) {
1283         len++;
1284         strval = g_malloc(len*sizeof(TCHAR));
1285         len = GetWindowText(hwnd, strval, len);
1286         ret = g_utf16_to_utf8(strval, -1, NULL, NULL, NULL);
1287         g_free(strval);
1288         return ret;
1289     } else {
1290         return NULL;
1291     }
1292 }
1293
1294
1295 /* XXX - Copied from "filter-util.c" in the wireshark-win32 branch */
1296 /* XXX - The only reason for the "filter_text" parameter is to be able to feed
1297  * in the "real" filter string in the case of a CBN_SELCHANGE notification message.
1298  */
1299 static void
1300 filter_tb_syntax_check(HWND hwnd, TCHAR *filter_text) {
1301     TCHAR     *strval = NULL;
1302     gint       len;
1303     dfilter_t *dfp;
1304
1305     /* If filter_text is non-NULL, use it.  Otherwise, grab the text from
1306      * the window */
1307     if (filter_text) {
1308         len = (lstrlen(filter_text) + 1) * sizeof(TCHAR);
1309         strval = g_malloc(len);
1310         memcpy(strval, filter_text, len);
1311     } else {
1312         len = GetWindowTextLength(hwnd);
1313         if (len > 0) {
1314             len++;
1315             strval = g_malloc(len*sizeof(TCHAR));
1316             len = GetWindowText(hwnd, strval, len);
1317         }
1318     }
1319
1320     if (len == 0) {
1321         /* Default window background */
1322         SendMessage(hwnd, EM_SETBKGNDCOLOR, (WPARAM) 1, COLOR_WINDOW);
1323         return;
1324     } else if (dfilter_compile(utf_16to8(strval), &dfp, NULL)) { /* colorize filter string entry */
1325         if (dfp != NULL)
1326             dfilter_free(dfp);
1327         /* Valid (light green) */
1328         SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, RGB(0xe4, 0xff, 0xc7)); /* tango_chameleon_1 */
1329     } else {
1330         /* Invalid (light red) */
1331         SendMessage(hwnd, EM_SETBKGNDCOLOR, 0, RGB(0xff, 0xcc, 0xcc)); /* tango_scarlet_red_1 */
1332     }
1333
1334     if (strval) g_free(strval);
1335 }
1336
1337
1338 static UINT_PTR CALLBACK
1339 open_file_hook_proc(HWND of_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1340     HWND      cur_ctrl, parent;
1341     OFNOTIFY *notify = (OFNOTIFY *) l_param;
1342     TCHAR     sel_name[MAX_PATH];
1343     gint      i;
1344
1345     switch(msg) {
1346         case WM_INITDIALOG:
1347             /* Retain the filter text, and fill it in. */
1348             if(g_dfilter_str != NULL) {
1349                 cur_ctrl = GetDlgItem(of_hwnd, EWFD_FILTER_EDIT);
1350                 SetWindowText(cur_ctrl, utf_8to16(g_dfilter_str));
1351             }
1352
1353             cur_ctrl = GetDlgItem(of_hwnd, EWFD_FORMAT_TYPE);
1354             SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) _T("Automatically detect file type"));
1355             for (i = 0; open_routines[i].name != NULL; i += 1) {
1356                 SendMessage(cur_ctrl, CB_ADDSTRING, 0, (WPARAM) utf_8to16(open_routines[i].name));
1357             }
1358             SendMessage(cur_ctrl, CB_SETCURSEL, 0, 0);
1359
1360             preview_set_file_info(of_hwnd, NULL);
1361             break;
1362         case WM_NOTIFY:
1363             switch (notify->hdr.code) {
1364                 case CDN_FILEOK:
1365                     /* Fetch the read filter */
1366                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_FILTER_EDIT);
1367                     if (g_dfilter_str)
1368                         g_free(g_dfilter_str);
1369                     g_dfilter_str = filter_tb_get(cur_ctrl);
1370
1371                     cur_ctrl = GetDlgItem(of_hwnd, EWFD_FORMAT_TYPE);
1372                     g_format_type = (unsigned int) SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0);
1373
1374                     break;
1375                 case CDN_SELCHANGE:
1376                     /* This _almost_ works correctly. We need to handle directory
1377                        selections, etc. */
1378                     parent = GetParent(of_hwnd);
1379                     CommDlg_OpenSave_GetFilePath(parent, sel_name, MAX_PATH);
1380                     preview_set_file_info(of_hwnd, utf_16to8(sel_name));
1381                     break;
1382                 case CDN_HELP:
1383                     topic_action(HELP_OPEN_WIN32_DIALOG);
1384                     break;
1385                 default:
1386                     break;
1387             }
1388             break;
1389         case WM_COMMAND:
1390             cur_ctrl = (HWND) l_param;
1391             switch(w_param) {
1392                 case (EN_UPDATE << 16) | EWFD_FILTER_EDIT:
1393                     filter_tb_syntax_check(cur_ctrl, NULL);
1394                     break;
1395                     /*
1396                      * If we ever figure out a way to integrate the Windows
1397                      * and GTK+ event loops (or make a native filter dialog),
1398                      * we can re-enable the "Filter" button.
1399                      */
1400                     /*
1401                 case EWFD_FILTER_BTN:
1402                     break;
1403                      */
1404                 default:
1405                     break;
1406             }
1407             break;
1408         default:
1409             break;
1410     }
1411     return 0;
1412 }
1413
1414 /* Generate a list of the file types we can filter for in the open dialog. */
1415 static void
1416 append_file_extension_type(GArray *sa, int et)
1417 {
1418     GString* pattern_str = g_string_new("");
1419     GString* description_str = g_string_new("");
1420     gchar sep;
1421     GSList *extensions_list, *extension;
1422     const TCHAR *str16;
1423     guint16 zero = 0;
1424
1425     /* Construct the list of patterns. */
1426     extensions_list = wtap_get_file_extension_type_extensions(et);
1427     g_string_printf(pattern_str, "");
1428     sep = '\0';
1429     for (extension = extensions_list; extension != NULL;
1430          extension = g_slist_next(extension)) {
1431         if (sep != '\0')
1432             g_string_append_c(pattern_str, sep);
1433         g_string_append_printf(pattern_str, "*.%s", (char *)extension->data);
1434         sep = ';';
1435     }
1436     wtap_free_extensions_list(extensions_list);
1437
1438     /* Construct the description. */
1439     g_string_printf(description_str, "%s (%s)",
1440                     wtap_get_file_extension_type_name(et),
1441                     pattern_str->str);
1442     str16 = utf_8to16(description_str->str);
1443     sa = g_array_append_vals(sa, str16, (guint) strlen(description_str->str));
1444     sa = g_array_append_val(sa, zero);
1445     g_string_free(description_str, TRUE);
1446
1447     str16 = utf_8to16(pattern_str->str);
1448     sa = g_array_append_vals(sa, str16, (guint) strlen(pattern_str->str));
1449     sa = g_array_append_val(sa, zero);
1450     g_string_free(pattern_str, TRUE);
1451 }
1452
1453 static TCHAR *
1454 build_file_open_type_list(void) {
1455     const TCHAR *str16;
1456     int et;
1457     GArray* sa;
1458     static const guint16 zero = 0;
1459     GString* pattern_str;
1460     gchar sep;
1461     GSList *extensions_list, *extension;
1462
1463     /*
1464      * Microsoft's UI guidelines say, of the file filters in open and
1465      * save dialogs:
1466      *
1467      *    For meta-filters, remove the file extension list to eliminate
1468      *    clutter. Examples: "All files," "All pictures," "All music,"
1469      *    and "All videos."
1470      *
1471      * so we omit them (for "All Capture Files", the filter would be
1472      * *really* long).  On both Windows XP and Windows 7, Wordpad doesn't
1473      * do that, but Paint does.
1474      */
1475
1476     /*
1477      * Array of hexadectets used as a sequence of null-terminated
1478      * UTF-16 strings.
1479      */
1480     sa = g_array_new(FALSE /*zero_terminated*/, FALSE /*clear_*/,2 /*element_size*/);
1481
1482     /* Add the "All Files" entry. */
1483     str16 = utf_8to16("All Files");
1484     sa = g_array_append_vals(sa, str16, (guint) strlen("All Files"));
1485     sa = g_array_append_val(sa, zero);
1486     str16 = utf_8to16(ALL_FILES_WILDCARD);
1487     sa = g_array_append_vals(sa, str16, (guint) strlen(ALL_FILES_WILDCARD));
1488     sa = g_array_append_val(sa, zero);
1489
1490     /*
1491      * Add an "All Capture Files" entry, with all the capture file
1492      * extensions we know about.
1493      */
1494     str16 = utf_8to16("All Capture Files");
1495     sa = g_array_append_vals(sa, str16, (guint) strlen("All Capture Files"));
1496     sa = g_array_append_val(sa, zero);
1497
1498     /*
1499      * Construct its list of patterns.
1500      */
1501     pattern_str = g_string_new("");
1502     extensions_list = wtap_get_all_capture_file_extensions_list();
1503     sep = '\0';
1504     for (extension = extensions_list; extension != NULL;
1505          extension = g_slist_next(extension)) {
1506         if (sep != '\0')
1507             g_string_append_c(pattern_str, sep);
1508         g_string_append_printf(pattern_str, "*.%s", (char *)extension->data);
1509         sep = ';';
1510     }
1511     wtap_free_extensions_list(extensions_list);
1512     str16 = utf_8to16(pattern_str->str);
1513     sa = g_array_append_vals(sa, str16, (guint) strlen(pattern_str->str));
1514     sa = g_array_append_val(sa, zero);
1515
1516     /* Include all the file type extensions Wireshark supports. */
1517     for (et = 0; et < wtap_get_num_file_type_extensions(); et++) {
1518         append_file_extension_type(sa, et);
1519     }
1520
1521     /* terminate the array */
1522     sa = g_array_append_val(sa, zero);
1523
1524     return (TCHAR *) g_array_free(sa, FALSE /*free_segment*/);
1525 }
1526
1527 /* Generate a list of the file types we can save this file as.
1528
1529    "g_filetype" is the type it has now.
1530
1531    "encap" is the encapsulation for its packets (which could be
1532    "unknown" or "per-packet").
1533
1534    "filtered" is TRUE if we're to save only the packets that passed
1535    the display filter (in which case we have to save it using Wiretap)
1536    and FALSE if we're to save the entire file (in which case, if we're
1537    saving it in the type it has already, we can just copy it).
1538
1539    The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
1540 */
1541 static void
1542 append_file_type(GArray *sa, int ft)
1543 {
1544     GString* pattern_str = g_string_new("");
1545     GString* description_str = g_string_new("");
1546     gchar sep;
1547     GSList *extensions_list, *extension;
1548     const TCHAR *str16;
1549     guint16 zero = 0;
1550
1551     extensions_list = wtap_get_file_extensions_list(ft, TRUE);
1552     if (extensions_list == NULL) {
1553         /* This file type doesn't have any particular extension
1554            conventionally used for it, so we'll just use a
1555            wildcard that matches all file names - even those with
1556            no extension, so we don't need to worry about compressed
1557            file extensions. */
1558            g_string_printf(pattern_str, ALL_FILES_WILDCARD);
1559     } else {
1560         /* Construct the list of patterns. */
1561         g_string_printf(pattern_str, "");
1562         sep = '\0';
1563         for (extension = extensions_list; extension != NULL;
1564              extension = g_slist_next(extension)) {
1565             if (sep != '\0')
1566                 g_string_append_c(pattern_str, sep);
1567             g_string_append_printf(pattern_str, "*.%s", (char *)extension->data);
1568             sep = ';';
1569         }
1570         wtap_free_extensions_list(extensions_list);
1571     }
1572
1573     /* Construct the description. */
1574     g_string_printf(description_str, "%s (%s)", wtap_file_type_subtype_string(ft),
1575                     pattern_str->str);
1576     str16 = utf_8to16(description_str->str);
1577     sa = g_array_append_vals(sa, str16, (guint) strlen(description_str->str));
1578     sa = g_array_append_val(sa, zero);
1579     g_string_free(description_str, TRUE);
1580
1581     str16 = utf_8to16(pattern_str->str);
1582     sa = g_array_append_vals(sa, str16, (guint) strlen(pattern_str->str));
1583     sa = g_array_append_val(sa, zero);
1584     g_string_free(pattern_str, TRUE);
1585 }
1586
1587 static TCHAR *
1588 build_file_save_type_list(GArray *savable_file_types) {
1589     guint i;
1590     int   ft;
1591     GArray* sa = g_array_new(FALSE /*zero_terminated*/, FALSE /*clear_*/,2 /*element_size*/);
1592     guint16 zero = 0;
1593
1594     /* Get only the file types as which we can save this file. */
1595     for (i = 0; i < savable_file_types->len; i++) {
1596         ft = g_array_index(savable_file_types, int, i);
1597         append_file_type(sa, ft);
1598     }
1599
1600     /* terminate the array */
1601     sa = g_array_append_val(sa, zero);
1602
1603     return (TCHAR *) g_array_free(sa, FALSE /*free_segment*/);
1604 }
1605
1606
1607 #if 0
1608 static void
1609 build_file_format_list(HWND sf_hwnd) {
1610     HWND  format_cb;
1611     int   ft;
1612     guint file_index;
1613     guint item_to_select;
1614     gchar *s;
1615
1616     /* Default to the first supported file type, if the file's current
1617        type isn't supported. */
1618     item_to_select = 0;
1619
1620     format_cb = GetDlgItem(sf_hwnd, EWFD_FILE_TYPE_COMBO);
1621     SendMessage(format_cb, CB_RESETCONTENT, 0, 0);
1622
1623     /* Check all file types. */
1624     file_index = 0;
1625     for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1626         if (ft == WTAP_FILE_UNKNOWN)
1627             continue;  /* not a real file type */
1628
1629         if (!packet_range_process_all(g_range) || ft != cfile.cd_t) {
1630             /* not all unfiltered packets or a different file type.  We have to use Wiretap. */
1631             if (!wtap_can_save_with_wiretap(ft, cfile.linktypes))
1632                 continue;       /* We can't. */
1633         }
1634
1635         /* OK, we can write it out in this type. */
1636         if(wtap_file_extensions_string(ft) != NULL) {
1637             s = g_strdup_printf("%s (%s)", wtap_file_type_string(ft), wtap_file_extensions_string(ft));
1638         } else {
1639             s = g_strdup_printf("%s (" ALL_FILES_WILDCARD ")", wtap_file_type_string(ft));
1640         }
1641         SendMessage(format_cb, CB_ADDSTRING, 0, (LPARAM) utf_8to16(s));
1642         g_free(s);
1643         SendMessage(format_cb, CB_SETITEMDATA, (LPARAM) file_index, (WPARAM) ft);
1644         if (ft == g_filetype) {
1645             /* Default to the same format as the file, if it's supported. */
1646             item_to_select = file_index;
1647         }
1648         file_index++;
1649     }
1650
1651     SendMessage(format_cb, CB_SETCURSEL, (WPARAM) item_to_select, 0);
1652 }
1653 #endif
1654
1655 static UINT_PTR CALLBACK
1656 save_as_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1657     HWND           cur_ctrl;
1658     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
1659     /*int            new_filetype, file_index;*/
1660
1661     switch(msg) {
1662         case WM_INITDIALOG: {
1663             OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
1664             capture_file *cf = (capture_file *) ofnp->lCustData;
1665             g_sf_hwnd = sf_hwnd;
1666
1667             /* Default to saving in the file's current format. */
1668             g_filetype = cf->cd_t;
1669
1670             /* Fill in the file format list */
1671             /*build_file_format_list(sf_hwnd);*/
1672             /* Fill in the compression checkbox */
1673             cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
1674             SendMessage(cur_ctrl, BM_SETCHECK, g_compressed, 0);
1675
1676             break;
1677         }
1678         case WM_COMMAND:
1679             cur_ctrl = (HWND) l_param;
1680
1681             switch (w_param) {
1682 #if 0
1683                 case (CBN_SELCHANGE << 16) | EWFD_FILE_TYPE_COMBO:
1684                     file_index = SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0);
1685                     if (file_index != CB_ERR) {
1686                         new_filetype = SendMessage(cur_ctrl, CB_GETITEMDATA, (WPARAM) file_index, 0);
1687                         if (new_filetype != CB_ERR) {
1688                             if (g_filetype != new_filetype) {
1689                                 if (wtap_can_save_with_wiretap(new_filetype, cfile.linktypes)) {
1690                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
1691                                     EnableWindow(cur_ctrl, TRUE);
1692                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
1693                                     EnableWindow(cur_ctrl, TRUE);
1694                                 } else {
1695                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
1696                                     SendMessage(cur_ctrl, BM_SETCHECK, 0, 0);
1697                                     EnableWindow(cur_ctrl, FALSE);
1698                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
1699                                     EnableWindow(cur_ctrl, FALSE);
1700                                 }
1701                                 g_filetype = new_filetype;
1702                                 cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
1703                                 if (wtap_dump_can_compress(file_type)) {
1704                                     EnableWindow(cur_ctrl);
1705                                 } else {
1706                                     g_compressed = FALSE;
1707                                     DisableWindow(cur_ctrl);
1708                                 }
1709                                 SendMessage(cur_ctrl, BM_SETCHECK, g_compressed, 0);
1710
1711                             }
1712                         }
1713                     }
1714                     break;
1715 #endif
1716                 default:
1717                     break;
1718             }
1719             break;
1720         case WM_NOTIFY:
1721             switch (notify->hdr.code) {
1722                 case CDN_HELP:
1723                     topic_action(HELP_SAVE_WIN32_DIALOG);
1724                     break;
1725                 case CDN_FILEOK: {
1726                     HWND   parent;
1727                     char  *file_name8;
1728                     OPENFILENAME *ofnp = (OPENFILENAME *) notify->lpOFN;
1729                     capture_file *cf = (capture_file *) ofnp->lCustData;
1730
1731                     /* Fetch our compression value */
1732                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
1733                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1734                         g_compressed = TRUE;
1735                     else
1736                         g_compressed = FALSE;
1737
1738                     /* Check if we're trying to overwrite the currently open file */
1739                     parent = GetParent(sf_hwnd);
1740                     file_name8 = utf_16to8(notify->lpOFN->lpstrFile);
1741                     if (files_identical(cf->filename, file_name8)) {
1742                         /* XXX: Is MessageBox the best way to pop up an error ? How to make text bold ? */
1743                         gchar *str = g_strdup_printf(
1744                             "Capture File \"%s\" identical to loaded file.\n\n"
1745                             "Please choose a different filename.",
1746                             file_name8);
1747                         MessageBox( parent, utf_8to16(str), _T("Error"), MB_ICONERROR | MB_APPLMODAL | MB_OK);
1748                         g_free(str);
1749                         SetWindowLongPtr(sf_hwnd, DWLP_MSGRESULT, 1L); /* Don't allow ! */
1750                         return 1;
1751                     }
1752                 }
1753                     break;
1754                 default:
1755                     break;
1756             }
1757             break;
1758         default:
1759             break;
1760     }
1761     return 0;
1762 }
1763
1764 static UINT_PTR CALLBACK
1765 save_as_statstree_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1766
1767     switch(msg) {
1768         case WM_INITDIALOG:
1769             g_sf_hwnd = sf_hwnd;
1770             break;
1771
1772         case WM_COMMAND:
1773             break;
1774
1775         case WM_NOTIFY:
1776             break;
1777
1778         default:
1779             break;
1780     }
1781     return 0;
1782 }
1783
1784 #define RANGE_TEXT_MAX 128
1785 static UINT_PTR CALLBACK
1786 export_specified_packets_file_hook_proc(HWND sf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
1787     HWND           cur_ctrl;
1788     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
1789     /*int            new_filetype, file_index;*/
1790
1791     switch(msg) {
1792         case WM_INITDIALOG: {
1793             g_sf_hwnd = sf_hwnd;
1794
1795             /* Default to saving all packets, in the file's current format. */
1796             g_filetype = g_cf->cd_t;
1797
1798             /* Fill in the file format list */
1799             /*build_file_format_list(sf_hwnd);*/
1800
1801             range_handle_wm_initdialog(sf_hwnd, g_range);
1802
1803             /* Fill in the compression checkbox */
1804             cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
1805             SendMessage(cur_ctrl, BM_SETCHECK, g_compressed, 0);
1806
1807             break;
1808         }
1809         case WM_COMMAND:
1810             cur_ctrl = (HWND) l_param;
1811
1812             switch (w_param) {
1813 #if 0
1814                 case (CBN_SELCHANGE << 16) | EWFD_FILE_TYPE_COMBO:
1815                     file_index = SendMessage(cur_ctrl, CB_GETCURSEL, 0, 0);
1816                     if (file_index != CB_ERR) {
1817                         new_filetype = SendMessage(cur_ctrl, CB_GETITEMDATA, (WPARAM) file_index, 0);
1818                         if (new_filetype != CB_ERR) {
1819                             if (g_filetype != new_filetype) {
1820                                 if (wtap_can_save_with_wiretap(new_filetype, cfile.linktypes)) {
1821                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
1822                                     EnableWindow(cur_ctrl, TRUE);
1823                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
1824                                     EnableWindow(cur_ctrl, TRUE);
1825                                 } else {
1826                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_CAPTURED_BTN);
1827                                     SendMessage(cur_ctrl, BM_SETCHECK, 0, 0);
1828                                     EnableWindow(cur_ctrl, FALSE);
1829                                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_DISPLAYED_BTN);
1830                                     EnableWindow(cur_ctrl, FALSE);
1831                                 }
1832                                 g_filetype = new_filetype;
1833                             }
1834                         }
1835                     }
1836                     break;
1837 #endif
1838                 default:
1839                     range_handle_wm_command(sf_hwnd, cur_ctrl, w_param, g_range);
1840                     break;
1841             }
1842             break;
1843         case WM_NOTIFY:
1844             switch (notify->hdr.code) {
1845                 case CDN_HELP:
1846                     topic_action(HELP_SAVE_WIN32_DIALOG);
1847                     break;
1848                 case CDN_FILEOK: {
1849                     HWND   parent;
1850                     char  *file_name8;
1851                     OPENFILENAME *ofnp = (OPENFILENAME *) notify->lpOFN;
1852                     capture_file *cf = (capture_file *) ofnp->lCustData;
1853
1854                     /* Fetch our compression value */
1855                     cur_ctrl = GetDlgItem(sf_hwnd, EWFD_GZIP_CB);
1856                     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1857                         g_compressed = TRUE;
1858                     else
1859                         g_compressed = FALSE;
1860
1861                     /* Check if we're trying to overwrite the currently open file */
1862                     parent = GetParent(sf_hwnd);
1863                     file_name8 = utf_16to8(notify->lpOFN->lpstrFile);
1864                     if (files_identical(cf->filename, file_name8)) {
1865                         /* XXX: Is MessageBox the best way to pop up an error ? How to make text bold ? */
1866                         gchar *str = g_strdup_printf(
1867                             "Capture File \"%s\" identical to loaded file.\n\n"
1868                             "Please choose a different filename.",
1869                             file_name8);
1870                         MessageBox( parent, utf_8to16(str), _T("Error"), MB_ICONERROR | MB_APPLMODAL | MB_OK);
1871                         g_free(str);
1872                         SetWindowLongPtr(sf_hwnd, DWLP_MSGRESULT, 1L); /* Don't allow ! */
1873                         return 1;
1874                     }
1875                 }
1876                     break;
1877                 default:
1878                     break;
1879             }
1880             break;
1881         default:
1882             break;
1883     }
1884     return 0;
1885 }
1886
1887
1888 #define STATIC_LABEL_CHARS 100
1889 /* For each range static control, fill in its value and enable/disable it. */
1890 static void
1891 range_update_dynamics(HWND dlg_hwnd, packet_range_t *range) {
1892     HWND     cur_ctrl;
1893     gboolean filtered_active = FALSE;
1894     TCHAR    static_val[STATIC_LABEL_CHARS];
1895     gint     selected_num;
1896     guint32  ignored_cnt = 0, displayed_ignored_cnt = 0;
1897     guint32  displayed_cnt;
1898     gboolean range_valid = TRUE;
1899
1900     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
1901     if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
1902         filtered_active = TRUE;
1903
1904     /* RANGE_SELECT_ALL */
1905     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_CAP);
1906     EnableWindow(cur_ctrl, !filtered_active);
1907     if (range->remove_ignored) {
1908         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), g_cf->count - range->ignored_cnt);
1909     } else {
1910         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), g_cf->count);
1911     }
1912     SetWindowText(cur_ctrl, static_val);
1913
1914     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_DISP);
1915     EnableWindow(cur_ctrl, filtered_active);
1916     if (range->include_dependents)
1917       displayed_cnt = range->displayed_plus_dependents_cnt;
1918     else
1919       displayed_cnt = range->displayed_cnt;
1920     if (range->remove_ignored) {
1921         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_cnt - range->displayed_ignored_cnt);
1922     } else {
1923         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_cnt);
1924     }
1925     SetWindowText(cur_ctrl, static_val);
1926
1927     /* RANGE_SELECT_CURR */
1928     selected_num = (g_cf->current_frame) ? g_cf->current_frame->num : 0;
1929     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_CAP);
1930     EnableWindow(cur_ctrl, selected_num && !filtered_active);
1931     if (range->remove_ignored && g_cf->current_frame && g_cf->current_frame->flags.ignored) {
1932         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("0"));
1933     } else {
1934         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%d"), selected_num ? 1 : 0);
1935     }
1936     SetWindowText(cur_ctrl, static_val);
1937
1938     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_DISP);
1939     EnableWindow(cur_ctrl, selected_num && filtered_active);
1940     if (range->remove_ignored && g_cf->current_frame && g_cf->current_frame->flags.ignored) {
1941         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("0"));
1942     } else {
1943         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%d"), selected_num ? 1 : 0);
1944     }
1945     SetWindowText(cur_ctrl, static_val);
1946
1947     /* RANGE_SELECT_MARKED */
1948     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
1949     EnableWindow(cur_ctrl, g_cf->marked_count);
1950
1951     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_CAP);
1952     EnableWindow(cur_ctrl, g_cf->marked_count && !filtered_active);
1953     if (range->remove_ignored) {
1954         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), g_cf->marked_count - range->ignored_marked_cnt);
1955     } else {
1956         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), g_cf->marked_count);
1957     }
1958     SetWindowText(cur_ctrl, static_val);
1959
1960     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_DISP);
1961     EnableWindow(cur_ctrl, g_cf->marked_count && filtered_active);
1962     if (range->remove_ignored) {
1963         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt - range->displayed_ignored_marked_cnt);
1964     } else {
1965         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_marked_cnt);
1966     }
1967     SetWindowText(cur_ctrl, static_val);
1968
1969     /* RANGE_SELECT_MARKED_RANGE */
1970     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
1971     EnableWindow(cur_ctrl, range->mark_range_cnt);
1972
1973     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_CAP);
1974     EnableWindow(cur_ctrl, range->mark_range_cnt && !filtered_active);
1975     if (range->remove_ignored) {
1976         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->mark_range_cnt - range->ignored_mark_range_cnt);
1977     } else {
1978         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->mark_range_cnt);
1979     }
1980     SetWindowText(cur_ctrl, static_val);
1981
1982     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_DISP);
1983     EnableWindow(cur_ctrl, range->displayed_mark_range_cnt && filtered_active);
1984     if (range->remove_ignored) {
1985         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt - range->displayed_ignored_mark_range_cnt);
1986     } else {
1987         StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_mark_range_cnt);
1988     }
1989     SetWindowText(cur_ctrl, static_val);
1990
1991     /* RANGE_SELECT_USER */
1992     switch (packet_range_check(range)) {
1993         case CVT_NO_ERROR:
1994             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
1995             SendMessage(cur_ctrl, EM_SETBKGNDCOLOR, (WPARAM) 1, COLOR_WINDOW);
1996
1997             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
1998             EnableWindow(cur_ctrl, !filtered_active);
1999             if (range->remove_ignored) {
2000                 StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->user_range_cnt - range->ignored_user_range_cnt);
2001             } else {
2002                 StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->user_range_cnt);
2003             }
2004             SetWindowText(cur_ctrl, static_val);
2005
2006             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
2007             EnableWindow(cur_ctrl, filtered_active);
2008             if (range->remove_ignored) {
2009                 StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_user_range_cnt - range->displayed_ignored_user_range_cnt);
2010             } else {
2011                 StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), range->displayed_user_range_cnt);
2012             }
2013             SetWindowText(cur_ctrl, static_val);
2014             break;
2015         case CVT_SYNTAX_ERROR:
2016             if (range->process == range_process_user_range) range_valid = FALSE;
2017             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
2018             SendMessage(cur_ctrl, EM_SETBKGNDCOLOR, 0, RGB(0xff, 0xcc, 0xcc));
2019             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
2020             SetWindowText(cur_ctrl, _T("Bad range"));
2021             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
2022             SetWindowText(cur_ctrl, _T("-"));
2023             break;
2024         case CVT_NUMBER_TOO_BIG:
2025             if (range->process == range_process_user_range) range_valid = FALSE;
2026             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
2027             SendMessage(cur_ctrl, EM_SETBKGNDCOLOR, 0, RGB(0xff, 0xcc, 0xcc));
2028             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_CAP);
2029             SetWindowText(cur_ctrl, _T("Too large"));
2030             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_DISP);
2031             SetWindowText(cur_ctrl, _T("-"));
2032            break;
2033
2034         default:
2035             g_assert_not_reached();
2036     }
2037
2038     /* RANGE_REMOVE_IGNORED_PACKETS */
2039     switch(range->process) {
2040         case(range_process_all):
2041             ignored_cnt = range->ignored_cnt;
2042             displayed_ignored_cnt = range->displayed_ignored_cnt;
2043             break;
2044         case(range_process_selected):
2045             ignored_cnt = (g_cf->current_frame && g_cf->current_frame->flags.ignored) ? 1 : 0;
2046             displayed_ignored_cnt = ignored_cnt;
2047             break;
2048         case(range_process_marked):
2049             ignored_cnt = range->ignored_marked_cnt;
2050             displayed_ignored_cnt = range->displayed_ignored_marked_cnt;
2051             break;
2052         case(range_process_marked_range):
2053             ignored_cnt = range->ignored_mark_range_cnt;
2054             displayed_ignored_cnt = range->displayed_ignored_mark_range_cnt;
2055             break;
2056         case(range_process_user_range):
2057             ignored_cnt = range->ignored_user_range_cnt;
2058             displayed_ignored_cnt = range->displayed_ignored_user_range_cnt;
2059             break;
2060         default:
2061             g_assert_not_reached();
2062     }
2063
2064     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_REMOVE_IGN_CB);
2065     EnableWindow(cur_ctrl, ignored_cnt);
2066
2067     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_IGNORED_CAP);
2068     EnableWindow(cur_ctrl, ignored_cnt && !filtered_active);
2069     StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), ignored_cnt);
2070     SetWindowText(cur_ctrl, static_val);
2071
2072     cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_IGNORED_DISP);
2073     EnableWindow(cur_ctrl, displayed_ignored_cnt && filtered_active);
2074     StringCchPrintf(static_val, STATIC_LABEL_CHARS, _T("%u"), displayed_ignored_cnt);
2075     SetWindowText(cur_ctrl, static_val);
2076
2077     cur_ctrl = GetDlgItem(GetParent(dlg_hwnd), IDOK);
2078     EnableWindow(cur_ctrl, range_valid);
2079 }
2080
2081 static void
2082 range_handle_wm_initdialog(HWND dlg_hwnd, packet_range_t *range) {
2083     HWND cur_ctrl;
2084
2085     /* Set the appropriate captured/displayed radio */
2086     if (range->process_filtered)
2087         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_DISPLAYED_BTN);
2088     else
2089         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
2090     SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
2091
2092     /* Retain the filter text, and fill it in. */
2093     if(range->user_range != NULL) {
2094         char* tmp_str;
2095         cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
2096         tmp_str = range_convert_range(NULL, range->user_range);
2097         SetWindowText(cur_ctrl, utf_8to16(tmp_str));
2098         wmem_free(NULL, tmp_str);
2099     }
2100
2101     /* dynamic values in the range frame */
2102     range_update_dynamics(dlg_hwnd, range);
2103
2104     /* Set the appropriate range radio */
2105     switch(range->process) {
2106         case(range_process_all):
2107             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_ALL_PKTS_BTN);
2108             break;
2109         case(range_process_selected):
2110             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_SEL_PKT_BTN);
2111             break;
2112         case(range_process_marked):
2113             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_MARKED_BTN);
2114             break;
2115         case(range_process_marked_range):
2116             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_FIRST_LAST_BTN);
2117             break;
2118         case(range_process_user_range):
2119             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
2120             break;
2121         default:
2122             g_assert_not_reached();
2123     }
2124     SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
2125 }
2126
2127 static void
2128 range_handle_wm_command(HWND dlg_hwnd, HWND ctrl, WPARAM w_param, packet_range_t *range) {
2129     HWND  cur_ctrl;
2130     TCHAR range_text[RANGE_TEXT_MAX];
2131
2132     if (!range) return;
2133
2134     switch(w_param) {
2135         case (BN_CLICKED << 16) | EWFD_CAPTURED_BTN:
2136         case (BN_CLICKED << 16) | EWFD_DISPLAYED_BTN:
2137             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_CAPTURED_BTN);
2138             if (SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
2139                 range->process_filtered = FALSE;
2140             else
2141                 range->process_filtered = TRUE;
2142             range_update_dynamics(dlg_hwnd, range);
2143             break;
2144         case (BN_CLICKED << 16) | EWFD_ALL_PKTS_BTN:
2145             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
2146                 range->process = range_process_all;
2147                 range_update_dynamics(dlg_hwnd, range);
2148             }
2149             break;
2150         case (BN_CLICKED << 16) | EWFD_SEL_PKT_BTN:
2151             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
2152                 range->process = range_process_selected;
2153                 range_update_dynamics(dlg_hwnd, range);
2154             }
2155             break;
2156         case (BN_CLICKED << 16) | EWFD_MARKED_BTN:
2157             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
2158                 range->process = range_process_marked;
2159                 range_update_dynamics(dlg_hwnd, range);
2160             }
2161             break;
2162         case (BN_CLICKED << 16) | EWFD_FIRST_LAST_BTN:
2163             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
2164                 range->process = range_process_marked_range;
2165                 range_update_dynamics(dlg_hwnd, range);
2166             }
2167             break;
2168         case (BN_CLICKED << 16) | EWFD_RANGE_BTN:
2169             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
2170                 range->process = range_process_user_range;
2171                 range_update_dynamics(dlg_hwnd, range);
2172                 cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_EDIT);
2173                 SetFocus(cur_ctrl);
2174             }
2175             break;
2176         case (EN_SETFOCUS << 16) | EWFD_RANGE_EDIT:
2177             cur_ctrl = GetDlgItem(dlg_hwnd, EWFD_RANGE_BTN);
2178             SendMessage(cur_ctrl, BM_CLICK, 0, 0);
2179             break;
2180         case (EN_UPDATE << 16) | EWFD_RANGE_EDIT:
2181             SendMessage(ctrl, WM_GETTEXT, (WPARAM) RANGE_TEXT_MAX, (LPARAM) range_text);
2182             packet_range_convert_str(range, utf_16to8(range_text));
2183             range_update_dynamics(dlg_hwnd, range);
2184             break;
2185         case (BN_CLICKED << 16) | EWFD_REMOVE_IGN_CB:
2186             if (SendMessage(ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
2187                 range->remove_ignored = TRUE;
2188             } else {
2189                 range->remove_ignored = FALSE;
2190             }
2191             range_update_dynamics(dlg_hwnd, range);
2192             break;
2193     }
2194 }
2195
2196 static UINT_PTR CALLBACK
2197 merge_file_hook_proc(HWND mf_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
2198     HWND      cur_ctrl, parent;
2199     OFNOTIFY *notify = (OFNOTIFY *) l_param;
2200     TCHAR     sel_name[MAX_PATH];
2201
2202     switch(msg) {
2203         case WM_INITDIALOG:
2204             /* Retain the filter text, and fill it in. */
2205             if(g_dfilter_str != NULL) {
2206                 cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
2207                 SetWindowText(cur_ctrl, utf_8to16(g_dfilter_str));
2208             }
2209
2210             /* Chrono by default */
2211             cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_CHRONO_BTN);
2212             SendMessage(cur_ctrl, BM_SETCHECK, TRUE, 0);
2213             g_merge_action = merge_append;
2214
2215             preview_set_file_info(mf_hwnd, NULL);
2216             break;
2217         case WM_NOTIFY:
2218             switch (notify->hdr.code) {
2219                 case CDN_FILEOK:
2220                     /* Fetch the read filter */
2221                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_FILTER_EDIT);
2222                     if (g_dfilter_str)
2223                         g_free(g_dfilter_str);
2224                     g_dfilter_str = filter_tb_get(cur_ctrl);
2225
2226                     cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_CHRONO_BTN);
2227                     if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
2228                         g_merge_action = merge_chrono;
2229                     } else {
2230                         cur_ctrl = GetDlgItem(mf_hwnd, EWFD_MERGE_PREPEND_BTN);
2231                         if(SendMessage(cur_ctrl, BM_GETCHECK, 0, 0) == BST_CHECKED) {
2232                             g_merge_action = merge_prepend;
2233                         }
2234                     }
2235
2236                     break;
2237                 case CDN_SELCHANGE:
2238                     /* This _almost_ works correctly.  We need to handle directory
2239                        selections, etc. */
2240                     parent = GetParent(mf_hwnd);
2241                     CommDlg_OpenSave_GetFilePath(parent, sel_name, MAX_PATH);
2242                     preview_set_file_info(mf_hwnd, utf_16to8(sel_name));
2243                     break;
2244                 case CDN_HELP:
2245                     topic_action(HELP_MERGE_WIN32_DIALOG);
2246                     break;
2247                 default:
2248                     break;
2249             }
2250             break;
2251         case WM_COMMAND:
2252             cur_ctrl = (HWND) l_param;
2253             switch(w_param) {
2254                 case (EN_UPDATE << 16) | EWFD_FILTER_EDIT:
2255                     filter_tb_syntax_check(cur_ctrl, NULL);
2256                     break;
2257                 default:
2258                     break;
2259             }
2260             break;
2261         default:
2262             break;
2263     }
2264     return 0;
2265 }
2266
2267
2268 static UINT_PTR CALLBACK
2269 export_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
2270     HWND           cur_ctrl;
2271     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
2272     gboolean       pkt_fmt_enable;
2273     int            i, filter_index;
2274
2275     switch(msg) {
2276         case WM_INITDIALOG: {
2277             OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
2278             capture_file *cf = (capture_file *) ofnp->lCustData;
2279
2280             /* init the printing range */
2281             packet_range_init(&print_args.range, cf);
2282             /* default to displayed packets */
2283             print_args.range.process_filtered = TRUE;
2284             range_handle_wm_initdialog(ef_hwnd, &print_args.range);
2285             format_handle_wm_initdialog(ef_hwnd, &print_args);
2286
2287             break;
2288         }
2289         case WM_COMMAND:
2290             cur_ctrl = (HWND) l_param;
2291             switch (w_param) {
2292                 case (CBN_SELCHANGE << 16) | EWFD_PKT_DETAIL_COMBO:
2293                 default:
2294                     range_handle_wm_command(ef_hwnd, cur_ctrl, w_param, &print_args.range);
2295                     print_update_dynamic(ef_hwnd, &print_args);
2296                     break;
2297             }
2298             break;
2299         case WM_NOTIFY:
2300             switch (notify->hdr.code) {
2301                 case CDN_FILEOK:
2302                     break;
2303                 case CDN_TYPECHANGE:
2304                     filter_index = notify->lpOFN->nFilterIndex;
2305
2306                     if (filter_index == 2)     /* PostScript */
2307                         print_args.format = PR_FMT_TEXT;
2308                     else
2309                         print_args.format = PR_FMT_PS;
2310                     if (filter_index == 3 || filter_index == 4 || filter_index == 5 || filter_index == 6)
2311                         pkt_fmt_enable = FALSE;
2312                     else
2313                         pkt_fmt_enable = TRUE;
2314                     for (i = EWFD_PKT_FORMAT_GB; i <= EWFD_PKT_NEW_PAGE_CB; i++) {
2315                         cur_ctrl = GetDlgItem(ef_hwnd, i);
2316                         EnableWindow(cur_ctrl, pkt_fmt_enable);
2317                     }
2318                     break;
2319                 case CDN_HELP:
2320                     topic_action(HELP_EXPORT_FILE_WIN32_DIALOG);
2321                     break;
2322                 default:
2323                     break;
2324             }
2325             break;
2326         default:
2327             break;
2328     }
2329     return 0;
2330 }
2331
2332 static UINT_PTR CALLBACK
2333 export_raw_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
2334     HWND          cur_ctrl;
2335     OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
2336     TCHAR         raw_msg[STATIC_LABEL_CHARS];
2337     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
2338
2339     switch(msg) {
2340         case WM_INITDIALOG:
2341             StringCchPrintf(raw_msg, STATIC_LABEL_CHARS, _T("%d byte%s of raw binary data will be written"),
2342                     ofnp->lCustData, utf_8to16(plurality(ofnp->lCustData, "", "s")));
2343             cur_ctrl = GetDlgItem(ef_hwnd, EWFD_EXPORTRAW_ST);
2344             SetWindowText(cur_ctrl, raw_msg);
2345             break;
2346         case WM_NOTIFY:
2347             switch (notify->hdr.code) {
2348                 case CDN_HELP:
2349                     topic_action(HELP_EXPORT_BYTES_WIN32_DIALOG);
2350                     break;
2351                 default:
2352                     break;
2353             }
2354         default:
2355             break;
2356     }
2357     return 0;
2358 }
2359
2360 static UINT_PTR CALLBACK
2361 export_sslkeys_file_hook_proc(HWND ef_hwnd, UINT msg, WPARAM w_param, LPARAM l_param) {
2362     HWND          cur_ctrl;
2363     OPENFILENAME *ofnp = (OPENFILENAME *) l_param;
2364     TCHAR         sslkeys_msg[STATIC_LABEL_CHARS];
2365     OFNOTIFY      *notify = (OFNOTIFY *) l_param;
2366
2367     switch(msg) {
2368         case WM_INITDIALOG:
2369             StringCchPrintf(sslkeys_msg, STATIC_LABEL_CHARS, _T("%d SSL Session Key%s will be written"),
2370                     ofnp->lCustData, utf_8to16(plurality(ofnp->lCustData, "", "s")));
2371             cur_ctrl = GetDlgItem(ef_hwnd, EWFD_EXPORTSSLKEYS_ST);
2372             SetWindowText(cur_ctrl, sslkeys_msg);
2373             break;
2374         case WM_NOTIFY:
2375             switch (notify->hdr.code) {
2376                 case CDN_HELP:
2377                     topic_action(HELP_EXPORT_BYTES_WIN32_DIALOG);
2378                     break;
2379                 default:
2380                     break;
2381             }
2382         default:
2383             break;
2384     }
2385     return 0;
2386 }
2387
2388 /*
2389  * Editor modelines
2390  *
2391  * Local Variables:
2392  * c-basic-offset: 4
2393  * tab-width: 8
2394  * indent-tabs-mode: nil
2395  * End:
2396  *
2397  * ex: set shiftwidth=4 tabstop=8 expandtab:
2398  * :indentSize=4:tabSize=8:noTabs=true:
2399  */