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