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