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