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